From 34d19f111ad8f8a7dfd4a71610b01b6846cba72a Mon Sep 17 00:00:00 2001 From: bft-codebot Date: Fri, 8 May 2026 05:02:57 +0000 Subject: [PATCH] sync(bfmono): feat(gambit): expose workloop task host service methods (+19 more) (bfmono@d0871fea7) This PR is an automated gambitmono sync of bfmono Gambit packages. - Source: `packages/gambit/` - Core: `packages/gambit/packages/gambit-core/` - bfmono rev: d0871fea7 Changes: - 412e36c9f feat(gambit): expose workloop task host service methods - bd65fd7bc fix(gambit): remove task delegation host service methods - 5776f3e98 feat(workloop): route runtime work through host services - af2da504c chore(gambit): cut 1.0.0-rc.2 - 84f610a1d docs(workloop): align Gambit brand hierarchy - ca4aff086 chore(gambit): remove legacy desktop fallbacks - e281e27f1 fix(gambit): hydrate chat transcript from persisted state - 35438f961 chore(gambit): record full precommit verification - e88e4957e docs(gambit): reposition around scenarios and graders - 2d2691076 fix(gambit): reject sandboxed chat runs - 98ab911eb docs(gambit): use canonical graders frontmatter - bb582eeb6 feat(gambit): improve chat event observability - 43e0588ba feat(gambit): stream and control chat turns - 538d0ad1b feat(gambit): add local deck chat repro server - 60078d9f6 fix(workloop): disable Codex websockets in chief runtime - 93d44fb06 fix(gambit): preserve whitespace in streamed assistant deltas - 76e21a05f fix(workloop): preserve Codex auth refresh failures - 224cfdca6 fix(gambit): fall back without host service token - 668e393de feat(gambit): add browser introspection live commands - 4d8a6ad7b feat(workloop): bridge runtime Codex refresh to host services Do not edit this repo directly; make changes in bfmono and re-run the sync. --- src/runtime_host_service.test.ts | 63 +++++++++++++++++++ src/runtime_host_service.ts | 100 ++++++++++++++++++++++++++++++- 2 files changed, 161 insertions(+), 2 deletions(-) diff --git a/src/runtime_host_service.test.ts b/src/runtime_host_service.test.ts index 339234e6..7c280bcd 100644 --- a/src/runtime_host_service.test.ts +++ b/src/runtime_host_service.test.ts @@ -5,6 +5,8 @@ import { callRuntimeHostServiceRaw, CREATE_WRITEBACK_PREVIEW_HOST_SERVICE_METHOD, validateRuntimeHostServiceMethodAndParams, + WORKLOOP_TASKS_DRAFT_HOST_SERVICE_METHOD, + WORKLOOP_TASKS_QUEUE_HOST_SERVICE_METHOD, } from "./runtime_host_service.ts"; async function readJsonLine(conn: Deno.Conn): Promise> { @@ -166,3 +168,64 @@ Deno.test("runtime host-service validates create writeback preview params", () = "workspaceRoot", ); }); + +Deno.test("runtime host-service validates Workloop task action params", () => { + assertEquals( + validateRuntimeHostServiceMethodAndParams({ + method: WORKLOOP_TASKS_DRAFT_HOST_SERVICE_METHOD, + params: { + acceptanceCriteria: ["Confirm queued state."], + purpose: "Smoke the task action host bridge.", + request: "Draft this task.", + targetCoworker: "assistant-to-chief-of-staff", + taskId: "bridge-smoke", + title: "Bridge smoke", + }, + }), + { + method: WORKLOOP_TASKS_DRAFT_HOST_SERVICE_METHOD, + params: { + acceptanceCriteria: ["Confirm queued state."], + purpose: "Smoke the task action host bridge.", + request: "Draft this task.", + scopePath: undefined, + targetCoworker: "assistant-to-chief-of-staff", + taskId: "bridge-smoke", + title: "Bridge smoke", + }, + }, + ); + assertEquals( + validateRuntimeHostServiceMethodAndParams({ + method: WORKLOOP_TASKS_QUEUE_HOST_SERVICE_METHOD, + params: { + request: "Queue this task.", + targetCoworker: "assistant-to-chief-of-staff", + taskId: "bridge-smoke", + }, + }), + { + method: WORKLOOP_TASKS_QUEUE_HOST_SERVICE_METHOD, + params: { + acceptanceCriteria: [], + request: "Queue this task.", + scopePath: undefined, + targetCoworker: "assistant-to-chief-of-staff", + taskId: "bridge-smoke", + title: undefined, + }, + }, + ); + assertThrows( + () => + validateRuntimeHostServiceMethodAndParams({ + method: WORKLOOP_TASKS_DRAFT_HOST_SERVICE_METHOD, + params: { + request: "Missing target coworker.", + title: "Invalid draft", + }, + }), + Error, + "targetCoworker", + ); +}); diff --git a/src/runtime_host_service.ts b/src/runtime_host_service.ts index 15751daf..ae0a3807 100644 --- a/src/runtime_host_service.ts +++ b/src/runtime_host_service.ts @@ -7,6 +7,8 @@ export const CODEX_REFRESH_HOST_SERVICE_METHOD = "providerAuth.codex.refreshChatgptTokens"; export const CREATE_WRITEBACK_PREVIEW_HOST_SERVICE_METHOD = "workloop.writebacks.createPreview"; +export const WORKLOOP_TASKS_DRAFT_HOST_SERVICE_METHOD = "workloop.tasks.draft"; +export const WORKLOOP_TASKS_QUEUE_HOST_SERVICE_METHOD = "workloop.tasks.queue"; export type RuntimeHostServiceFailureReason = | "host_auth_missing" @@ -33,13 +35,36 @@ export type CreateWritebackPreviewHostServiceParams = { changedPaths?: Array; }; +export type WorkloopTasksDraftHostServiceParams = { + acceptanceCriteria?: Array; + purpose?: string | null; + request: string; + scopePath?: string | null; + targetCoworker: string; + taskId?: string | null; + title: string; +}; + +export type WorkloopTasksQueueHostServiceParams = { + acceptanceCriteria?: Array; + request?: string | null; + scopePath?: string | null; + targetCoworker: string; + taskId?: string | null; + title?: string | null; +}; + export type RuntimeHostServiceMethod = | typeof CODEX_REFRESH_HOST_SERVICE_METHOD - | typeof CREATE_WRITEBACK_PREVIEW_HOST_SERVICE_METHOD; + | typeof CREATE_WRITEBACK_PREVIEW_HOST_SERVICE_METHOD + | typeof WORKLOOP_TASKS_DRAFT_HOST_SERVICE_METHOD + | typeof WORKLOOP_TASKS_QUEUE_HOST_SERVICE_METHOD; export type RuntimeHostServiceParams = | CodexRefreshHostServiceParams - | CreateWritebackPreviewHostServiceParams; + | CreateWritebackPreviewHostServiceParams + | WorkloopTasksDraftHostServiceParams + | WorkloopTasksQueueHostServiceParams; export type RuntimeHostServiceRequest = { id: string; @@ -153,6 +178,59 @@ export function validateCreateWritebackPreviewHostServiceParams( }; } +function normalizeNullableOptionalString( + value: unknown, + label: string, +): string | null | undefined { + if (value == null) return value === null ? null : undefined; + return normalizeRequiredString(value, label); +} + +export function validateWorkloopTasksDraftHostServiceParams( + value: unknown, +): WorkloopTasksDraftHostServiceParams { + if (!isRecord(value)) { + throw new Error("host service params must be a JSON object."); + } + return { + acceptanceCriteria: normalizeStringArray( + value.acceptanceCriteria, + "acceptanceCriteria", + ), + purpose: normalizeNullableOptionalString(value.purpose, "purpose"), + request: normalizeRequiredString(value.request, "request"), + scopePath: normalizeNullableOptionalString(value.scopePath, "scopePath"), + targetCoworker: normalizeRequiredString( + value.targetCoworker, + "targetCoworker", + ), + taskId: normalizeNullableOptionalString(value.taskId, "taskId"), + title: normalizeRequiredString(value.title, "title"), + }; +} + +export function validateWorkloopTasksQueueHostServiceParams( + value: unknown, +): WorkloopTasksQueueHostServiceParams { + if (!isRecord(value)) { + throw new Error("host service params must be a JSON object."); + } + return { + acceptanceCriteria: normalizeStringArray( + value.acceptanceCriteria, + "acceptanceCriteria", + ), + request: normalizeNullableOptionalString(value.request, "request"), + scopePath: normalizeNullableOptionalString(value.scopePath, "scopePath"), + targetCoworker: normalizeRequiredString( + value.targetCoworker, + "targetCoworker", + ), + taskId: normalizeNullableOptionalString(value.taskId, "taskId"), + title: normalizeNullableOptionalString(value.title, "title"), + }; +} + export function validateRuntimeHostServiceMethodAndParams(input: { method: string; params: unknown; @@ -164,6 +242,14 @@ export function validateRuntimeHostServiceMethodAndParams(input: { | { method: typeof CREATE_WRITEBACK_PREVIEW_HOST_SERVICE_METHOD; params: CreateWritebackPreviewHostServiceParams; + } + | { + method: typeof WORKLOOP_TASKS_DRAFT_HOST_SERVICE_METHOD; + params: WorkloopTasksDraftHostServiceParams; + } + | { + method: typeof WORKLOOP_TASKS_QUEUE_HOST_SERVICE_METHOD; + params: WorkloopTasksQueueHostServiceParams; } { switch (input.method) { case CODEX_REFRESH_HOST_SERVICE_METHOD: @@ -176,6 +262,16 @@ export function validateRuntimeHostServiceMethodAndParams(input: { method: CREATE_WRITEBACK_PREVIEW_HOST_SERVICE_METHOD, params: validateCreateWritebackPreviewHostServiceParams(input.params), }; + case WORKLOOP_TASKS_DRAFT_HOST_SERVICE_METHOD: + return { + method: WORKLOOP_TASKS_DRAFT_HOST_SERVICE_METHOD, + params: validateWorkloopTasksDraftHostServiceParams(input.params), + }; + case WORKLOOP_TASKS_QUEUE_HOST_SERVICE_METHOD: + return { + method: WORKLOOP_TASKS_QUEUE_HOST_SERVICE_METHOD, + params: validateWorkloopTasksQueueHostServiceParams(input.params), + }; default: throw new Error( `unsupported runtime host service method: ${input.method}`,