Skip to content

Commit c99bae4

Browse files
committed
chore: sync hive
1 parent bc1a763 commit c99bae4

2 files changed

Lines changed: 8 additions & 5 deletions

File tree

β€Ž.hive/issues.jsonlβ€Ž

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -779,12 +779,13 @@
779779
{"id":"opencode-next--xts0a-mjx87bibiol","title":"Stream.asyncScoped for merged-stream","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-02T18:47:16.739Z","updated_at":"2026-01-02T18:58:40.654Z","closed_at":"2026-01-02T18:58:40.654Z","parent_id":"opencode-next--xts0a-mjx87bhmq39","dependencies":[],"labels":[],"comments":[]}
780780
{"id":"opencode-next--xts0a-mjx932w6bvg","title":"Integrate @opencode-ai/sdk types into core package","description":"Replace hand-rolled domain types in packages/core/src/types/domain.ts with official SDK types from @opencode-ai/sdk.\n\nSDK types include:\n- Part types (TextPart, ToolPart, etc.) with sessionID field\n- Message types (UserMessage, AssistantMessage)\n- Session types\n- Event types (EventMessagePartUpdated, etc.)\n\nBenefits:\n- Single source of truth\n- No type drift\n- sessionID properly typed on parts\n\nSteps:\n1. Add @opencode-ai/sdk as dependency to packages/core\n2. Re-export SDK types from packages/core/src/types/domain.ts\n3. Update imports across codebase\n4. Remove hand-rolled types that duplicate SDK","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-02T19:11:58.566Z","updated_at":"2026-01-02T19:11:58.566Z","dependencies":[],"labels":[],"comments":[]}
781781
{"id":"opencode-next--xts0a-mjx98fq0r4u","title":"Refactor to use @opencode-ai/sdk types","description":"Replace hand-rolled domain types with official SDK types. First commit current work, create changeset, sweep docs. Then add SDK as peerDep, create re-export layer, update all consumers.","status":"open","priority":1,"issue_type":"epic","created_at":"2026-01-02T19:16:08.472Z","updated_at":"2026-01-02T19:16:08.472Z","dependencies":[],"labels":[],"comments":[]}
782-
{"id":"opencode-next--xts0a-mjx98fq7wss","title":"Commit current work + create changeset","status":"open","priority":0,"issue_type":"task","created_at":"2026-01-02T19:16:08.479Z","updated_at":"2026-01-02T19:16:08.479Z","parent_id":"opencode-next--xts0a-mjx98fq0r4u","dependencies":[],"labels":[],"comments":[]}
783-
{"id":"opencode-next--xts0a-mjx98fqgj7x","title":"Sweep READMEs and AGENTS.md with current state","status":"open","priority":0,"issue_type":"task","created_at":"2026-01-02T19:16:08.488Z","updated_at":"2026-01-02T19:16:08.488Z","parent_id":"opencode-next--xts0a-mjx98fq0r4u","dependencies":[],"labels":[],"comments":[]}
784-
{"id":"opencode-next--xts0a-mjx98fqihkr","title":"Add @opencode-ai/sdk as peerDep + devDep","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-02T19:16:08.490Z","updated_at":"2026-01-02T19:16:08.490Z","parent_id":"opencode-next--xts0a-mjx98fq0r4u","dependencies":[],"labels":[],"comments":[]}
785-
{"id":"opencode-next--xts0a-mjx98fqk6e0","title":"Create sdk.ts re-export layer for SDK types","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-02T19:16:08.492Z","updated_at":"2026-01-02T19:16:08.492Z","parent_id":"opencode-next--xts0a-mjx98fq0r4u","dependencies":[],"labels":[],"comments":[]}
786-
{"id":"opencode-next--xts0a-mjx98fqmy1x","title":"Update domain.ts to re-export from sdk.ts","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-02T19:16:08.494Z","updated_at":"2026-01-02T19:16:08.494Z","parent_id":"opencode-next--xts0a-mjx98fq0r4u","dependencies":[],"labels":[],"comments":[]}
787782
{"id":"opencode-next--xts0a-mjx98fqnuez","title":"Update events.ts to use SDK event types","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-02T19:16:08.495Z","updated_at":"2026-01-02T19:16:08.495Z","parent_id":"opencode-next--xts0a-mjx98fq0r4u","dependencies":[],"labels":[],"comments":[]}
788783
{"id":"opencode-next--xts0a-mjx98fqp3ck","title":"Update world layer imports (atoms, merged-stream, types)","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-02T19:16:08.497Z","updated_at":"2026-01-02T19:16:08.497Z","parent_id":"opencode-next--xts0a-mjx98fq0r4u","dependencies":[],"labels":[],"comments":[]}
789784
{"id":"opencode-next--xts0a-mjx98fqq068","title":"Update swarm-cli output.ts event handling","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-02T19:16:08.498Z","updated_at":"2026-01-02T19:16:08.498Z","parent_id":"opencode-next--xts0a-mjx98fq0r4u","dependencies":[],"labels":[],"comments":[]}
790785
{"id":"opencode-next--xts0a-mjx98fqtfwh","title":"Verify typecheck + tests pass","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-02T19:16:08.501Z","updated_at":"2026-01-02T19:16:08.501Z","parent_id":"opencode-next--xts0a-mjx98fq0r4u","dependencies":[],"labels":[],"comments":[]}
786+
{"id":"opencode-next--xts0a-mjx98fq7wss","title":"Commit current work + create changeset","status":"closed","priority":0,"issue_type":"task","created_at":"2026-01-02T19:16:08.479Z","updated_at":"2026-01-02T19:19:21.249Z","closed_at":"2026-01-02T19:19:21.249Z","parent_id":"opencode-next--xts0a-mjx98fq0r4u","dependencies":[],"labels":[],"comments":[]}
787+
{"id":"opencode-next--xts0a-mjx98fqgj7x","title":"Sweep READMEs and AGENTS.md with current state","status":"closed","priority":0,"issue_type":"task","created_at":"2026-01-02T19:16:08.488Z","updated_at":"2026-01-02T19:21:55.683Z","closed_at":"2026-01-02T19:21:55.683Z","parent_id":"opencode-next--xts0a-mjx98fq0r4u","dependencies":[],"labels":[],"comments":[]}
788+
{"id":"opencode-next--xts0a-mjx98fqihkr","title":"Add @opencode-ai/sdk as peerDep + devDep","description":"BLOCKED: Version spec in task (>=0.1.0, ^0.1.0) doesn't match published SDK versions (1.0.x). Awaiting coordinator guidance on correct version specification.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-02T19:16:08.490Z","updated_at":"2026-01-02T19:25:03.582Z","closed_at":"2026-01-02T19:25:03.582Z","parent_id":"opencode-next--xts0a-mjx98fq0r4u","dependencies":[],"labels":[],"comments":[]}
789+
{"id":"opencode-next--xts0a-mjx98fqk6e0","title":"Create sdk.ts re-export layer for SDK types","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-02T19:16:08.492Z","updated_at":"2026-01-02T19:25:13.206Z","closed_at":"2026-01-02T19:25:13.206Z","parent_id":"opencode-next--xts0a-mjx98fq0r4u","dependencies":[],"labels":[],"comments":[]}
790+
{"id":"opencode-next--xts0a-mjx98fqmy1x","title":"Update domain.ts to re-export from sdk.ts","status":"blocked","priority":2,"issue_type":"task","created_at":"2026-01-02T19:16:08.494Z","updated_at":"2026-01-02T19:27:32.906Z","parent_id":"opencode-next--xts0a-mjx98fq0r4u","dependencies":[],"labels":[],"comments":[]}
791+
{"id":"opencode-next--xts0a-mjx9as7sqhl","title":"Schedule.repeat for SSE discovery loop","description":"Replace while+sleep discovery loop in sse.ts with Schedule.repeat.\n\nCURRENT (line 360):\n```typescript\nwhile (this.running) {\n const servers = yield* discoverServers()...\n yield* Effect.sleep(this.config.discoveryIntervalMs) // 5000ms\n}\n```\n\nTARGET:\n```typescript\nconst discoveryEffect = Effect.gen(this, function* () {\n const servers = yield* discoverServers()...\n})\n\nthis.discoveryFiber = Effect.runFork(\n discoveryEffect.pipe(\n Effect.repeat(Schedule.fixed(Duration.millis(5000)))\n )\n)\n```\n\nBENEFITS:\n- Cleaner, declarative timing\n- Better Effect ecosystem integration \n- Easier to test with TestClock\n- Automatic cleanup with Scope\n\nNOTE: Do NOT touch the connection retry loop (line 406) - that has custom exponential backoff logic and should stay as-is.\n\nRUN TESTS: bun run test packages/core/src/world/sse","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-02T19:17:57.976Z","updated_at":"2026-01-02T19:29:07.031Z","closed_at":"2026-01-02T19:29:07.031Z","dependencies":[],"labels":[],"comments":[]}

β€Ž.hive/memories.jsonlβ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1302,6 +1302,7 @@
13021302
{"id":"mem-24eb46468ceac457","information":"Contributor @torvalds: Linus Torvalds. Filed issue #123","created_at":"2025-12-27T02:32:09.684Z","tags":"contributor,torvalds,issue-123"}
13031303
{"id":"mem-24fc9d8d6ff5587a","information":"Memory in custom collection","created_at":"2025-12-31T19:12:54.294Z","tags":"test"}
13041304
{"id":"mem-252df974a7244535","information":"Memory to validate - VALTEST789","created_at":"2025-12-30T02:04:14.390Z","tags":"test,validate"}
1305+
{"id":"mem-25867bc6b78b46c5","information":"SDK Type Migration Gotcha (opencode-next): @opencode-ai/sdk types are NOT backward compatible with hand-rolled domain types. Key incompatibilities: (1) Session requires projectID: string and version: number (previously optional/missing), (2) Message is discriminated union UserMessage | AssistantMessage with many required fields (agent, model, time, parentID for assistant, etc.) vs loose shape with [key: string]: unknown, (3) Part types use strict discriminated unions - TextPart.text NOT Part.content, (4) SessionStatus is object type { type: \"idle\" } | { type: \"running\" } NOT string union \"idle\" | \"running\". Impact: Directly re-exporting SDK types breaks 100+ test files. Solution: Either create compatibility layer that maps SDK β†’ loose types, or migrate all tests to strict SDK types (separate epic). Don't assume SDK re-export is drop-in replacement.","created_at":"2026-01-02T19:27:49.152Z","tags":"typescript,sdk,type-migration,backward-compatibility,breaking-change,opencode-next,domain-types"}
13051306
{"id":"mem-25ad096bfc1f102c","information":"Full content test EXPANDTEST789","created_at":"2025-12-31T19:18:32.054Z","tags":"test,expand"}
13061307
{"id":"mem-25fc4d59209ed87a","information":"Contributor @torvalds: Linus Torvalds. Filed issue #123","created_at":"2025-12-26T23:14:18.762Z","tags":"contributor,torvalds,issue-123"}
13071308
{"id":"mem-260a3f65e79d260f","information":"UploadThing Factory Pattern Analysis - Provider-Free Hooks with SSR Hydration\n\n## Core Pattern: Factory Function with Type Binding\n\n```typescript\n// Factory function that binds FileRouter type\nexport const generateReactHelpers = <TRouter extends FileRouter>(\n initOpts?: GenerateTypedHelpersOptions,\n) => {\n const fetch = initOpts?.fetch ?? globalThis.fetch;\n const url = resolveMaybeUrlArg(initOpts?.url);\n\n // Generate client helpers with bound types\n const clientHelpers = genUploader<TRouter>({ fetch, url, package: \"@uploadthing/react\" });\n\n // Return hook factory with pre-bound URL and FileRouter generic\n function useUploadThing<TEndpoint extends keyof TRouter>(\n endpoint: EndpointArg<TRouter, TEndpoint>,\n opts?: UseUploadthingProps<TRouter[TEndpoint]>,\n ) {\n return __useUploadThingInternal(url, endpoint, fetch, opts);\n }\n\n function getRouteConfig(slug: EndpointArg<TRouter, keyof TRouter>) {\n const maybeServerData = globalThis.__UPLOADTHING;\n const endpoint = unwrap(slug, clientHelpers.routeRegistry);\n const config = maybeServerData?.find((x) => x.slug === endpoint)?.config;\n if (!config) {\n throw new Error(`No config found for endpoint. Use NextSSRPlugin.`);\n }\n return config;\n }\n\n return { useUploadThing, ...clientHelpers, getRouteConfig } as const;\n};\n```\n\n## Usage Pattern (3-File Setup)\n\n```typescript\n// 1. Server: Define router (server/uploadthing.ts)\nexport const uploadRouter = {\n videoAndImage: f({ image: { maxFileSize: \"32MB\" } })\n .middleware(({ req, files }) => ({ foo: \"bar\" }))\n .onUploadComplete(({ file, metadata }) => console.log(\"done\", file)),\n};\nexport type OurFileRouter = typeof uploadRouter;\n\n// 2. Client: Generate typed helpers (utils/uploadthing.ts)\nimport { generateReactHelpers } from \"@uploadthing/react\";\nimport type { OurFileRouter } from \"~/server/uploadthing\";\n\nexport const { useUploadThing } = generateReactHelpers<OurFileRouter>();\n\n// 3. Layout: SSR hydration (app/layout.tsx)\nimport { NextSSRPlugin } from \"@uploadthing/react/next-ssr-plugin\";\nimport { extractRouterConfig } from \"uploadthing/server\";\nimport { uploadRouter } from \"~/server/uploadthing\";\n\nexport default function RootLayout({ children }) {\n return (\n <html>\n <body>\n <NextSSRPlugin routerConfig={extractRouterConfig(uploadRouter)} />\n {children}\n </body>\n </html>\n );\n}\n```\n\n## SSR Hydration Mechanism (NextSSRPlugin)\n\n```typescript\n\"use client\";\nimport { useId } from \"react\";\nimport { useServerInsertedHTML } from \"next/navigation\";\n\ndeclare const globalThis: { __UPLOADTHING?: EndpointMetadata };\n\nexport function NextSSRPlugin(props: { routerConfig: EndpointMetadata }) {\n const id = useId();\n\n // Set routerConfig on server globalThis (for RSC)\n globalThis.__UPLOADTHING = props.routerConfig;\n\n // Inject script tag to hydrate client globalThis\n useServerInsertedHTML(() => {\n const html = [\n `globalThis.__UPLOADTHING = ${JSON.stringify(props.routerConfig)};`,\n ];\n return <script key={id} dangerouslySetInnerHTML={{ __html: html.join(\"\") }} />;\n });\n\n return null;\n}\n```\n\n**How it works:**\n1. Server renders: `globalThis.__UPLOADTHING` set in RSC context\n2. `useServerInsertedHTML` injects `<script>` tag into HTML stream\n3. Client hydrates: `globalThis.__UPLOADTHING` available before React hydration\n4. Hooks check `globalThis.__UPLOADTHING` first, fallback to fetch if missing\n\n## Type Inference Flow\n\n```typescript\n// Server router type\ntype FileRouter = Record<string, AnyFileRoute>;\n\n// Factory binds router type\ngenerateReactHelpers<OurFileRouter>()\n\n// Hook infers endpoint from router\nuseUploadThing<TEndpoint extends keyof TRouter>(\n endpoint: EndpointArg<TRouter, TEndpoint>,\n opts?: UseUploadthingProps<TRouter[TEndpoint]>\n)\n\n// Types flow through:\n// - inferEndpointInput<TRouter[TEndpoint]> β†’ input validation\n// - inferEndpointOutput<TRouter[TEndpoint]> β†’ onClientUploadComplete result\n// - inferErrorShape<TRouter[TEndpoint]> β†’ onUploadError type\n```\n\n## Identity Proxy Pattern (Route Registry)\n\n```typescript\n// Creates proxy that returns property name as value\nexport function createIdentityProxy<TObj extends Record<string, unknown>>() {\n return new Proxy(noop, {\n get: (_, prop) => prop,\n }) as unknown as TObj;\n}\n\n// Usage: Type-safe endpoint selection\nconst routeRegistry = createIdentityProxy<RouteRegistry<TRouter>>();\nconst endpoint = typeof slug === \"function\" ? slug(routeRegistry) : slug;\n\n// Allows: useUploadThing((r) => r.videoAndImage) OR useUploadThing(\"videoAndImage\")\n```\n\n## extractRouterConfig (Server β†’ Client Config)\n\n```typescript\n// Server-side: Extract route metadata from FileRouter\nexport const extractRouterConfig = <TRouter extends FileRouter>(router: TRouter) =>\n Effect.forEach(objectKeys(router), (slug) =>\n Effect.map(fillInputRouteConfig(router[slug]!.routerConfig), (config) => ({\n slug,\n config,\n })),\n );\n\n// Returns: EndpointMetadata = Array<{ slug: string, config: ExpandedRouteConfig }>\n// Config includes: maxFileSize, maxFileCount, contentDisposition, acl\n```\n\n## Key Insights for OpenCode\n\n1. **No Provider Needed**: Factory function closes over config (url, fetch), returns pre-bound hooks\n2. **Type Safety**: Generic `<TRouter>` flows through entire chain (factory β†’ hook β†’ callbacks)\n3. **SSR Hydration**: `globalThis` + `useServerInsertedHTML` eliminates loading states\n4. **Identity Proxy**: Enables both string and function endpoint selection with full type safety\n5. **Config Extraction**: Server router metadata becomes client-accessible via SSR plugin\n6. **Dual globalThis**: Set on server (RSC), injected to client (script tag), checked in hooks\n\n## Comparison to OpenCode Current Pattern\n\nUploadThing:\n- Factory returns hooks (no provider)\n- SSR plugin injects config via globalThis\n- Types bound at factory call site\n\nOpenCode (current):\n- Provider wraps app\n- Config passed via context\n- Types bound at provider level\n\nUploadThing advantage: Simpler DX (no provider nesting), faster hydration (no context propagation)","created_at":"2025-12-31T04:00:46.583Z","tags":"uploadthing,factory-pattern,ssr-plugin,adr-013,provider-free,type-inference,globalThis,useServerInsertedHTML,identity-proxy"}
@@ -1536,6 +1537,7 @@
15361537
{"id":"mem-6f8b1af2964acc4d","information":"Memory with metadata","created_at":"2025-12-30T02:03:12.364Z","metadata":"{\"source\":\"test\",\"priority\":\"high\"}","tags":"test"}
15371538
{"id":"mem-70424f0f707cdb5c","information":"Next.js API Route Testing Pattern - Vitest Mock Strategy for Fetch\n\n**Pattern for testing Next.js route handlers with mocked fetch:**\n\n1. **Setup/Teardown:**\n```typescript\nlet originalFetch: typeof global.fetch\nbeforeEach(() => { originalFetch = global.fetch })\nafterEach(() => { global.fetch = originalFetch; vi.restoreAllMocks() })\n```\n\n2. **Mock fetch with type safety:**\n```typescript\nconst mockFetch = vi.fn().mockResolvedValue({\n ok: true,\n status: 200,\n headers: new Headers({ \"content-type\": \"application/json\" }),\n text: vi.fn().mockResolvedValue('{\"data\": \"test\"}'),\n})\nglobal.fetch = mockFetch as unknown as typeof fetch\n```\n\n3. **Extract call arguments with proper typing:**\n```typescript\nconst fetchOptions = mockFetch.mock.calls[0]?.[1] as { headers: Headers; method: string }\nexpect(fetchOptions.headers.get(\"x-opencode-directory\")).toBe(\"/path\")\n```\n\n**Key Gotchas:**\n\n1. **Next.js 16 Async Params:** Route context params MUST be awaited:\n```typescript\nconst { port, path } = await context.params // NOT { params: { port } }\n```\n\n2. **Test params as Promises:**\n```typescript\nconst params = Promise.resolve({ port: \"4056\", path: [\"sessions\"] })\nawait GET(request, { params })\n```\n\n3. **204 No Content Bug:** NextResponse constructor throws on 204 status with body. Route must check status and return `new NextResponse(null, { status: 204 })` for no-body responses (204, 205, 304).\n\n**Coverage Strategy:**\n- Port validation (invalid, out-of-range, boundaries)\n- Path construction (root, nested, deep)\n- Header forwarding (preserve specific headers, handle missing)\n- All HTTP methods (GET, POST, PUT, PATCH, DELETE, OPTIONS)\n- Error scenarios (connection failures, upstream errors, non-Error exceptions)\n- Response handling (content-type preservation, large bodies)\n- Integration scenarios (full lifecycle tests)\n\n**Pattern from:** apps/web/src/app/api/opencode/[port]/[[...path]]/route.test.ts (32 tests, 100% pass rate)","created_at":"2025-12-31T04:28:39.619Z","tags":"nextjs-16,vitest,testing,route-handlers,fetch-mocking,api-testing,async-params,type-safety"}
15381539
{"id":"mem-708776a58ffdd2d8","information":"OAuth tokens need 5min buffer before expiry to avoid race conditions in src/auth.ts","created_at":"2026-01-01T05:02:14.745Z","tags":"auth,oauth,gotcha"}
1540+
{"id":"mem-70cf3e0ea0a2d2f6","information":"Type consolidation task verification pattern (opencode-next): When tasked with \"update imports after type consolidation\", VERIFY FIRST before assuming changes needed. In this case, all world layer files (atoms.ts, merged-stream.ts, types.ts) already had correct imports from ../types/domain.js and ../types/events.js. The strategy \"keep existing imports, they will re-export SDK types\" meant NO CODE CHANGES were required. Type errors in TEST FILES are a separate concern - don't expand scope. Pattern: (1) Read all assigned files, (2) Check current imports, (3) If imports already match strategy, complete with no changes, (4) Don't fix unrelated test failures unless in scope.","created_at":"2026-01-02T19:27:32.498Z","tags":"type-consolidation,import-verification,scope-management,opencode-next,world-layer,test-files"}
15391541
{"id":"mem-71125aec6788eda3","information":"Memory in custom collection","created_at":"2025-12-30T02:46:30.787Z","tags":"test"}
15401542
{"id":"mem-716134086639fe57","information":"Memory to retrieve by ID - GETTEST456","created_at":"2025-12-31T19:18:32.179Z","tags":"test,get"}
15411543
{"id":"mem-718627b7a1164d1a","information":"OAuth refresh tokens need 5min buffer before expiry","created_at":"2025-12-30T02:47:48.636Z","metadata":"{\"domain\":\"auth\",\"topic\":\"tokens\"}","tags":"auth,integration-test"}

0 commit comments

Comments
Β (0)