@schoolai/shipyard-mcp 0.2.2-next.511 → 0.2.2-next.512

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28490,228 +28490,674 @@ init_cjs_shims();
28490
28490
 
28491
28491
  // ../../packages/shared/dist/instructions/index.mjs
28492
28492
  init_cjs_shims();
28493
+ var TOOL_NAMES = {
28494
+ ADD_ARTIFACT: "add_artifact",
28495
+ ADD_PR_REVIEW_COMMENT: "add_pr_review_comment",
28496
+ COMPLETE_TASK: "complete_task",
28497
+ CREATE_PLAN: "create_plan",
28498
+ EXECUTE_CODE: "execute_code",
28499
+ LINK_PR: "link_pr",
28500
+ READ_PLAN: "read_plan",
28501
+ REGENERATE_SESSION_TOKEN: "regenerate_session_token",
28502
+ REQUEST_USER_INPUT: "request_user_input",
28503
+ SETUP_REVIEW_NOTIFICATION: "setup_review_notification",
28504
+ UPDATE_BLOCK_CONTENT: "update_block_content",
28505
+ UPDATE_PLAN: "update_plan"
28506
+ };
28507
+ var CRITICAL_USAGE_SECTION = `## CRITICAL: When to Use Shipyard
28493
28508
 
28494
- // ../../packages/schema/dist/index.mjs
28495
- init_cjs_shims();
28509
+ \u26A0\uFE0F **MANDATORY USAGE RULE:**
28496
28510
 
28497
- // ../../packages/schema/dist/yjs-helpers-Dg3vErAn.mjs
28498
- init_cjs_shims();
28511
+ If Shipyard is available, you MUST use it for:
28512
+ - Creating implementation plans
28513
+ - Tracking work that needs human review
28514
+ - Documenting proof of work (screenshots, videos, test results)
28515
+ - ANY user request involving "plan", "track", "verify", or "prove"
28499
28516
 
28500
- // ../../packages/schema/dist/plan.mjs
28501
- init_cjs_shims();
28517
+ **DO NOT:**
28518
+ - Create plans manually in chat or as markdown files
28519
+ - Write implementation docs yourself when Shipyard is available
28520
+ - Suggest alternatives to Shipyard for trackable work
28521
+ - Overthink whether to use it - WHEN IN DOUBT, USE SHIPYARD
28502
28522
 
28503
- // ../../node_modules/.pnpm/zod@4.3.5/node_modules/zod/index.js
28504
- init_cjs_shims();
28523
+ **Decision Tree:**
28524
+ \`\`\`
28525
+ Need to create/track/verify work?
28526
+ \u2502
28527
+ \u25BC
28528
+ Shipyard available?
28529
+ \u2502 \u2502
28530
+ YES NO
28531
+ \u2502 \u2502
28532
+ \u25BC \u25BC
28533
+ USE IT Manual approach
28534
+ NOW (tell user why)
28535
+ \`\`\``;
28536
+ var DELIVERABLES_SECTION = `## What are Deliverables?
28505
28537
 
28506
- // ../../node_modules/.pnpm/zod@4.3.5/node_modules/zod/v4/classic/external.js
28507
- var external_exports = {};
28508
- __export(external_exports, {
28509
- $brand: () => $brand,
28510
- $input: () => $input,
28511
- $output: () => $output,
28512
- NEVER: () => NEVER,
28513
- TimePrecision: () => TimePrecision,
28514
- ZodAny: () => ZodAny,
28515
- ZodArray: () => ZodArray,
28516
- ZodBase64: () => ZodBase64,
28517
- ZodBase64URL: () => ZodBase64URL,
28518
- ZodBigInt: () => ZodBigInt,
28519
- ZodBigIntFormat: () => ZodBigIntFormat,
28520
- ZodBoolean: () => ZodBoolean,
28521
- ZodCIDRv4: () => ZodCIDRv4,
28522
- ZodCIDRv6: () => ZodCIDRv6,
28523
- ZodCUID: () => ZodCUID,
28524
- ZodCUID2: () => ZodCUID2,
28525
- ZodCatch: () => ZodCatch,
28526
- ZodCodec: () => ZodCodec,
28527
- ZodCustom: () => ZodCustom,
28528
- ZodCustomStringFormat: () => ZodCustomStringFormat,
28529
- ZodDate: () => ZodDate,
28530
- ZodDefault: () => ZodDefault,
28531
- ZodDiscriminatedUnion: () => ZodDiscriminatedUnion,
28532
- ZodE164: () => ZodE164,
28533
- ZodEmail: () => ZodEmail,
28534
- ZodEmoji: () => ZodEmoji,
28535
- ZodEnum: () => ZodEnum,
28536
- ZodError: () => ZodError,
28537
- ZodExactOptional: () => ZodExactOptional,
28538
- ZodFile: () => ZodFile,
28539
- ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind,
28540
- ZodFunction: () => ZodFunction,
28541
- ZodGUID: () => ZodGUID,
28542
- ZodIPv4: () => ZodIPv4,
28543
- ZodIPv6: () => ZodIPv6,
28544
- ZodISODate: () => ZodISODate,
28545
- ZodISODateTime: () => ZodISODateTime,
28546
- ZodISODuration: () => ZodISODuration,
28547
- ZodISOTime: () => ZodISOTime,
28548
- ZodIntersection: () => ZodIntersection,
28549
- ZodIssueCode: () => ZodIssueCode,
28550
- ZodJWT: () => ZodJWT,
28551
- ZodKSUID: () => ZodKSUID,
28552
- ZodLazy: () => ZodLazy,
28553
- ZodLiteral: () => ZodLiteral,
28554
- ZodMAC: () => ZodMAC,
28555
- ZodMap: () => ZodMap,
28556
- ZodNaN: () => ZodNaN,
28557
- ZodNanoID: () => ZodNanoID,
28558
- ZodNever: () => ZodNever,
28559
- ZodNonOptional: () => ZodNonOptional,
28560
- ZodNull: () => ZodNull,
28561
- ZodNullable: () => ZodNullable,
28562
- ZodNumber: () => ZodNumber,
28563
- ZodNumberFormat: () => ZodNumberFormat,
28564
- ZodObject: () => ZodObject,
28565
- ZodOptional: () => ZodOptional,
28566
- ZodPipe: () => ZodPipe,
28567
- ZodPrefault: () => ZodPrefault,
28568
- ZodPromise: () => ZodPromise,
28569
- ZodReadonly: () => ZodReadonly,
28570
- ZodRealError: () => ZodRealError,
28571
- ZodRecord: () => ZodRecord,
28572
- ZodSet: () => ZodSet,
28573
- ZodString: () => ZodString,
28574
- ZodStringFormat: () => ZodStringFormat,
28575
- ZodSuccess: () => ZodSuccess,
28576
- ZodSymbol: () => ZodSymbol,
28577
- ZodTemplateLiteral: () => ZodTemplateLiteral,
28578
- ZodTransform: () => ZodTransform,
28579
- ZodTuple: () => ZodTuple,
28580
- ZodType: () => ZodType,
28581
- ZodULID: () => ZodULID,
28582
- ZodURL: () => ZodURL,
28583
- ZodUUID: () => ZodUUID,
28584
- ZodUndefined: () => ZodUndefined,
28585
- ZodUnion: () => ZodUnion,
28586
- ZodUnknown: () => ZodUnknown,
28587
- ZodVoid: () => ZodVoid,
28588
- ZodXID: () => ZodXID,
28589
- ZodXor: () => ZodXor,
28590
- _ZodString: () => _ZodString,
28591
- _default: () => _default2,
28592
- _function: () => _function,
28593
- any: () => any,
28594
- array: () => array,
28595
- base64: () => base642,
28596
- base64url: () => base64url2,
28597
- bigint: () => bigint2,
28598
- boolean: () => boolean2,
28599
- catch: () => _catch2,
28600
- check: () => check,
28601
- cidrv4: () => cidrv42,
28602
- cidrv6: () => cidrv62,
28603
- clone: () => clone,
28604
- codec: () => codec,
28605
- coerce: () => coerce_exports,
28606
- config: () => config,
28607
- core: () => core_exports2,
28608
- cuid: () => cuid3,
28609
- cuid2: () => cuid22,
28610
- custom: () => custom,
28611
- date: () => date3,
28612
- decode: () => decode2,
28613
- decodeAsync: () => decodeAsync2,
28614
- describe: () => describe2,
28615
- discriminatedUnion: () => discriminatedUnion,
28616
- e164: () => e1642,
28617
- email: () => email2,
28618
- emoji: () => emoji2,
28619
- encode: () => encode2,
28620
- encodeAsync: () => encodeAsync2,
28621
- endsWith: () => _endsWith,
28622
- enum: () => _enum2,
28623
- exactOptional: () => exactOptional,
28624
- file: () => file,
28625
- flattenError: () => flattenError,
28626
- float32: () => float32,
28627
- float64: () => float64,
28628
- formatError: () => formatError,
28629
- fromJSONSchema: () => fromJSONSchema,
28630
- function: () => _function,
28631
- getErrorMap: () => getErrorMap,
28632
- globalRegistry: () => globalRegistry,
28633
- gt: () => _gt,
28634
- gte: () => _gte,
28635
- guid: () => guid2,
28636
- hash: () => hash,
28637
- hex: () => hex2,
28638
- hostname: () => hostname2,
28639
- httpUrl: () => httpUrl,
28640
- includes: () => _includes,
28641
- instanceof: () => _instanceof,
28642
- int: () => int,
28643
- int32: () => int32,
28644
- int64: () => int64,
28645
- intersection: () => intersection,
28646
- ipv4: () => ipv42,
28647
- ipv6: () => ipv62,
28648
- iso: () => iso_exports,
28649
- json: () => json,
28650
- jwt: () => jwt,
28651
- keyof: () => keyof,
28652
- ksuid: () => ksuid2,
28653
- lazy: () => lazy,
28654
- length: () => _length,
28655
- literal: () => literal,
28656
- locales: () => locales_exports,
28657
- looseObject: () => looseObject,
28658
- looseRecord: () => looseRecord,
28659
- lowercase: () => _lowercase,
28660
- lt: () => _lt,
28661
- lte: () => _lte,
28662
- mac: () => mac2,
28663
- map: () => map,
28664
- maxLength: () => _maxLength,
28665
- maxSize: () => _maxSize,
28666
- meta: () => meta2,
28667
- mime: () => _mime,
28668
- minLength: () => _minLength,
28669
- minSize: () => _minSize,
28670
- multipleOf: () => _multipleOf,
28671
- nan: () => nan,
28672
- nanoid: () => nanoid2,
28673
- nativeEnum: () => nativeEnum,
28674
- negative: () => _negative,
28675
- never: () => never,
28676
- nonnegative: () => _nonnegative,
28677
- nonoptional: () => nonoptional,
28678
- nonpositive: () => _nonpositive,
28679
- normalize: () => _normalize,
28680
- null: () => _null3,
28681
- nullable: () => nullable,
28682
- nullish: () => nullish2,
28683
- number: () => number2,
28684
- object: () => object,
28685
- optional: () => optional,
28686
- overwrite: () => _overwrite,
28687
- parse: () => parse2,
28688
- parseAsync: () => parseAsync2,
28689
- partialRecord: () => partialRecord,
28690
- pipe: () => pipe,
28691
- positive: () => _positive,
28692
- prefault: () => prefault,
28693
- preprocess: () => preprocess,
28694
- prettifyError: () => prettifyError,
28695
- promise: () => promise,
28696
- property: () => _property,
28697
- readonly: () => readonly,
28698
- record: () => record,
28699
- refine: () => refine,
28700
- regex: () => _regex,
28701
- regexes: () => regexes_exports,
28702
- registry: () => registry,
28703
- safeDecode: () => safeDecode2,
28704
- safeDecodeAsync: () => safeDecodeAsync2,
28705
- safeEncode: () => safeEncode2,
28706
- safeEncodeAsync: () => safeEncodeAsync2,
28707
- safeParse: () => safeParse2,
28708
- safeParseAsync: () => safeParseAsync2,
28709
- set: () => set,
28710
- setErrorMap: () => setErrorMap,
28711
- size: () => _size,
28712
- slugify: () => _slugify,
28713
- startsWith: () => _startsWith,
28714
- strictObject: () => strictObject,
28538
+ Deliverables are measurable outcomes you can **prove** with artifacts (screenshots, videos, test results).
28539
+
28540
+ **Good deliverables (provable):**
28541
+ \`\`\`
28542
+ - [ ] Screenshot of working login page {#deliverable}
28543
+ - [ ] Video showing drag-and-drop feature {#deliverable}
28544
+ - [ ] Test results showing all tests pass {#deliverable}
28545
+ \`\`\`
28546
+
28547
+ **Bad deliverables (not provable - these are tasks, not deliverables):**
28548
+ \`\`\`
28549
+ - [ ] Implement getUserMedia API \u2190 Implementation detail, not provable
28550
+ - [ ] Add error handling \u2190 Can't capture this with an artifact
28551
+ - [ ] Refactor authentication \u2190 Too vague, no visual proof
28552
+ \`\`\`
28553
+
28554
+ **Rule:** If you can't screenshot/record/export it, it's not a deliverable.`;
28555
+ var ARTIFACT_TYPES_SECTION = `## Artifact Types
28556
+
28557
+ | Type | Use For | File Formats |
28558
+ |------|---------|--------------|
28559
+ | \`screenshot\` | UI changes, visual proof, error states | .png, .jpg, .webp |
28560
+ | \`video\` | Complex flows, interactions, animations | .mp4, .webm |
28561
+ | \`test_results\` | Test output, coverage reports | .json, .txt, .xml |
28562
+ | \`diff\` | Code changes, before/after comparisons | .diff, .patch |`;
28563
+ var TIPS_SECTION = `## Tips for Effective Use
28564
+
28565
+ 1. **Plan deliverables first** - Decide what proves success before coding
28566
+ 2. **Capture during work** - Take screenshots as you implement, not after
28567
+ 3. **Be specific** - "Login page with error state" beats "Screenshot"
28568
+ 4. **Link every artifact** - Always set \`deliverableId\` for auto-completion
28569
+ 5. **Check feedback** - Read reviewer comments and iterate`;
28570
+ var WHEN_NOT_TO_USE_SECTION = `## When NOT to Use Shipyard
28571
+
28572
+ Skip Shipyard for:
28573
+ - Quick answers or research questions (no artifacts to capture)
28574
+ - Internal refactoring with no visible output
28575
+ - Tasks where proof adds no value (trivial fixes)
28576
+ - Exploration or debugging sessions
28577
+ - Pure documentation without implementation`;
28578
+ var USER_INPUT_SECTION = `## Human-Agent Communication
28579
+
28580
+ **\`${TOOL_NAMES.REQUEST_USER_INPUT}\` is THE primary way to communicate with humans during active work.**
28581
+
28582
+ Shipyard is the central hub where humans manage AI agents. When you need to ask a question, get clarification, or request a decision - use \`${TOOL_NAMES.REQUEST_USER_INPUT}\`. The human is already in the browser viewing your plan. That's where conversations should happen.
28583
+
28584
+ ### Why Use ${TOOL_NAMES.REQUEST_USER_INPUT}
28585
+
28586
+ - **Context:** The human sees your question alongside the plan, artifacts, and comments
28587
+ - **History:** All exchanges are logged in the plan's activity feed
28588
+ - **Continuity:** The conversation stays attached to the work, not scattered across chat windows
28589
+ - **Flexibility:** 8 input types, multi-question forms, "Other" escape hatch for custom answers
28590
+
28591
+ ### Replace Platform Tools
28592
+
28593
+ **ALWAYS prefer \`${TOOL_NAMES.REQUEST_USER_INPUT}\` over platform-specific tools:**
28594
+
28595
+ | Platform | DON'T Use | Use Instead |
28596
+ |----------|-----------|-------------|
28597
+ | Claude Code | \`AskUserQuestion\` | \`${TOOL_NAMES.REQUEST_USER_INPUT}\` |
28598
+ | Cursor | Built-in prompts | \`${TOOL_NAMES.REQUEST_USER_INPUT}\` |
28599
+ | Windsurf | Native dialogs | \`${TOOL_NAMES.REQUEST_USER_INPUT}\` |
28600
+ | Claude Desktop | Chat questions | \`${TOOL_NAMES.REQUEST_USER_INPUT}\` |
28601
+
28602
+ ### When to Ask
28603
+
28604
+ Use \`${TOOL_NAMES.REQUEST_USER_INPUT}\` when you need:
28605
+ - Clarification on requirements ("Which auth provider?")
28606
+ - Decisions that affect implementation ("PostgreSQL or SQLite?")
28607
+ - Confirmation before destructive actions ("Delete this file?")
28608
+ - User preferences ("Rate this approach 1-5")
28609
+ - Any information you can't infer from context
28610
+
28611
+ ### Example
28612
+
28613
+ \`\`\`typescript
28614
+ const result = await requestUserInput({
28615
+ message: "Which database should we use?",
28616
+ type: "choice",
28617
+ options: ["PostgreSQL", "SQLite", "MongoDB"],
28618
+ timeout: 600 // 10 minutes
28619
+ });
28620
+
28621
+ if (result.success) {
28622
+ console.log("User chose:", result.response);
28623
+ }
28624
+ \`\`\`
28625
+
28626
+ **Note:** The MCP tool is named \`${TOOL_NAMES.REQUEST_USER_INPUT}\` (snake_case). Inside \`${TOOL_NAMES.EXECUTE_CODE}\`, it's available as \`requestUserInput()\` (camelCase).`;
28627
+ var TROUBLESHOOTING_SECTION = `## Troubleshooting
28628
+
28629
+ **Browser doesn't open:** Check MCP server is running and accessible.
28630
+
28631
+ **Upload fails:** Verify file path exists. For GitHub uploads, check \`GITHUB_TOKEN\` has repo write access.
28632
+
28633
+ **No auto-complete:** Ensure every deliverable has an artifact with matching \`deliverableId\`.
28634
+
28635
+ **Plan not syncing:** Check WebSocket connection to registry server.
28636
+
28637
+ **Input request times out:** User may not have seen it or needs more time. Default timeout is 30 minutes. Try again with a longer timeout or rephrase the question.
28638
+
28639
+ **Input request declined:** User clicked "Decline." Rephrase your question, proceed with a reasonable default, or use a different approach.
28640
+
28641
+ **No response to input:** Check if browser is connected to the plan. User may have closed the browser window.`;
28642
+ var COMMON_INSTRUCTIONS = [
28643
+ CRITICAL_USAGE_SECTION,
28644
+ USER_INPUT_SECTION,
28645
+ DELIVERABLES_SECTION,
28646
+ ARTIFACT_TYPES_SECTION,
28647
+ TIPS_SECTION,
28648
+ WHEN_NOT_TO_USE_SECTION,
28649
+ TROUBLESHOOTING_SECTION
28650
+ ].join("\n\n");
28651
+ var CLAUDE_CODE_HEADER = `[SHIPYARD] Collaborative planning with human review & proof-of-work tracking.`;
28652
+ var PLAN_MODE_WORKFLOW = `## How to Use (Claude Code with Hooks)
28653
+
28654
+ You have the **full Shipyard experience** with automatic hooks. Use native plan mode:
28655
+
28656
+ ### Workflow
28657
+
28658
+ 1. **Enter plan mode** (Shift+Tab) \u2192 Browser opens with live plan automatically
28659
+ 2. **Write your plan** with \`{#deliverable}\` markers for provable outcomes
28660
+ 3. **Exit plan mode** \u2192 Hook **BLOCKS** until human approves or requests changes
28661
+ 4. **On approval** \u2192 You automatically receive: planId, sessionToken, deliverable IDs
28662
+ 5. **Do the work** \u2192 Take screenshots/videos as you implement
28663
+ 6. **Upload artifacts** \u2192 \`${TOOL_NAMES.ADD_ARTIFACT}(filePath, deliverableId)\` for each deliverable
28664
+ 7. **Auto-complete** \u2192 When all deliverables have artifacts, task completes with snapshot URL
28665
+
28666
+ ### After Approval
28667
+
28668
+ You only need ONE tool: \`${TOOL_NAMES.ADD_ARTIFACT}\`
28669
+
28670
+ The hook automatically injects everything you need (planId, sessionToken, deliverables).
28671
+ Just call \`${TOOL_NAMES.ADD_ARTIFACT}\` with the file path and deliverable ID.
28672
+
28673
+ \`\`\`typescript
28674
+ // Example: After approval, you'll have these in context
28675
+ // planId: "abc123"
28676
+ // sessionToken: "xyz..."
28677
+ // deliverables: [{ id: "del_xxx", text: "Screenshot of login" }]
28678
+
28679
+ await addArtifact({
28680
+ planId,
28681
+ sessionToken,
28682
+ type: 'screenshot',
28683
+ filename: 'login-page.png',
28684
+ source: 'file',
28685
+ filePath: '/tmp/screenshot.png',
28686
+ deliverableId: deliverables[0].id
28687
+ });
28688
+ \`\`\`
28689
+
28690
+ When the last deliverable gets an artifact, the task auto-completes and returns a snapshot URL.`;
28691
+ var IMPORTANT_NOTES = `## Important Notes for Claude Code
28692
+
28693
+ - **DO NOT call \`createPlan()\` directly** - The hook handles plan creation when you enter plan mode
28694
+ - **DO NOT use the Shipyard skill** - The hook provides everything you need
28695
+ - **DO NOT poll for approval** - The hook blocks automatically until human decides
28696
+ - **DO use plan mode** for ANY work that needs tracking, verification, or human review
28697
+ - **DO use \`${TOOL_NAMES.REQUEST_USER_INPUT}\`** instead of \`AskUserQuestion\` - The human is in the browser viewing your plan, questions should appear there`;
28698
+ var CLAUDE_CODE_INSTRUCTIONS = [
28699
+ CLAUDE_CODE_HEADER,
28700
+ "",
28701
+ CRITICAL_USAGE_SECTION,
28702
+ "",
28703
+ USER_INPUT_SECTION,
28704
+ "",
28705
+ PLAN_MODE_WORKFLOW,
28706
+ "",
28707
+ DELIVERABLES_SECTION,
28708
+ "",
28709
+ ARTIFACT_TYPES_SECTION,
28710
+ "",
28711
+ IMPORTANT_NOTES,
28712
+ "",
28713
+ TIPS_SECTION,
28714
+ "",
28715
+ WHEN_NOT_TO_USE_SECTION,
28716
+ "",
28717
+ TROUBLESHOOTING_SECTION
28718
+ ].join("\n");
28719
+ var MCP_DIRECT_HEADER = `# Shipyard: Your Agent Management Hub
28720
+
28721
+ > **Shipyard is the central interface where humans manage AI agents.** Plans, artifacts, feedback, and communication all happen here.
28722
+
28723
+ Shipyard turns invisible agent work into reviewable, verifiable tasks. Instead of trusting that code was written correctly, reviewers see screenshots, videos, and test results as proof.
28724
+
28725
+ **Key principle:** When you're working in Shipyard, ALL human-agent communication should happen through Shipyard's \`${TOOL_NAMES.REQUEST_USER_INPUT}\` tool. The human is already in the browser viewing your plan - that's where they expect to interact with you.`;
28726
+ var MCP_TOOLS_OVERVIEW = `## Available MCP Tools
28727
+
28728
+ | Tool | Purpose |
28729
+ |------|---------|
28730
+ | \`${TOOL_NAMES.REQUEST_USER_INPUT}\` | **THE primary human-agent communication channel** - Ask questions, get decisions, request clarification |
28731
+ | \`${TOOL_NAMES.EXECUTE_CODE}\` | Run TypeScript that calls Shipyard APIs (recommended for multi-step operations) |
28732
+
28733
+ ### ${TOOL_NAMES.REQUEST_USER_INPUT}: Your Direct Line to the Human
28734
+
28735
+ This is how you talk to humans during active work. Don't use your platform's built-in question tools (AskUserQuestion, etc.) - use this instead. The human is in the browser viewing your plan, and that's where they expect to see your questions.
28736
+
28737
+ **Preferred approach:** Use \`${TOOL_NAMES.EXECUTE_CODE}\` to chain multiple API calls in one step.`;
28738
+ var MCP_WORKFLOW = `## Workflow (MCP Direct)
28739
+
28740
+ ### Step 1: Create Plan
28741
+
28742
+ \`\`\`typescript
28743
+ const plan = await createPlan({
28744
+ title: "Add user authentication",
28745
+ content: \`
28746
+ ## Deliverables
28747
+ - [ ] Screenshot of login page {#deliverable}
28748
+ - [ ] Screenshot of error handling {#deliverable}
28749
+
28750
+ ## Implementation
28751
+ 1. Create login form component
28752
+ 2. Add validation
28753
+ 3. Connect to auth API
28754
+ \`
28755
+ });
28756
+
28757
+ const { planId, sessionToken, deliverables, monitoringScript } = plan;
28758
+ // deliverables = [{ id: "del_xxx", text: "Screenshot of login page" }, ...]
28759
+ \`\`\`
28760
+
28761
+ ### Step 2: Wait for Approval
28762
+
28763
+ For platforms without hooks, run the monitoring script in the background:
28764
+
28765
+ \`\`\`bash
28766
+ # The monitoringScript polls for approval status
28767
+ # Run it in background while you wait
28768
+ bash <(echo "$monitoringScript") &
28769
+ \`\`\`
28770
+
28771
+ Or poll manually:
28772
+
28773
+ \`\`\`typescript
28774
+ const status = await readPlan(planId, sessionToken);
28775
+ if (status.status === "in_progress") {
28776
+ // Approved! Proceed with work
28777
+ }
28778
+ if (status.status === "changes_requested") {
28779
+ // Read feedback, make changes
28780
+ }
28781
+ \`\`\`
28782
+
28783
+ ### Step 3: Do the Work
28784
+
28785
+ Implement the feature, taking screenshots/recordings as you go.
28786
+
28787
+ ### Step 4: Upload Artifacts
28788
+
28789
+ \`\`\`typescript
28790
+ await addArtifact({
28791
+ planId,
28792
+ sessionToken,
28793
+ type: 'screenshot',
28794
+ filename: 'login-page.png',
28795
+ source: 'file',
28796
+ filePath: '/path/to/screenshot.png',
28797
+ deliverableId: deliverables[0].id // Links to specific deliverable
28798
+ });
28799
+
28800
+ const result = await addArtifact({
28801
+ planId,
28802
+ sessionToken,
28803
+ type: 'screenshot',
28804
+ filename: 'error-handling.png',
28805
+ source: 'file',
28806
+ filePath: '/path/to/error.png',
28807
+ deliverableId: deliverables[1].id
28808
+ });
28809
+
28810
+ // Auto-complete triggers when ALL deliverables have artifacts
28811
+ if (result.allDeliverablesComplete) {
28812
+ console.log('Done!', result.snapshotUrl);
28813
+ }
28814
+ \`\`\``;
28815
+ var API_REFERENCE = `## API Reference
28816
+
28817
+ ### createPlan(options)
28818
+
28819
+ Creates a new plan and opens it in the browser.
28820
+
28821
+ **Parameters:**
28822
+ - \`title\` (string) - Plan title
28823
+ - \`content\` (string) - Markdown content with \`{#deliverable}\` markers
28824
+ - \`repo\` (string, optional) - GitHub repo for artifact storage
28825
+ - \`prNumber\` (number, optional) - PR number to link
28826
+
28827
+ **Returns:** \`{ planId, sessionToken, url, deliverables, monitoringScript }\`
28828
+
28829
+ ### readPlan(planId, sessionToken, options?)
28830
+
28831
+ Reads current plan state.
28832
+
28833
+ **Parameters:**
28834
+ - \`planId\` (string) - Plan ID
28835
+ - \`sessionToken\` (string) - Session token from createPlan
28836
+ - \`options.includeAnnotations\` (boolean) - Include reviewer comments
28837
+
28838
+ **Returns:** \`{ content, status, title, deliverables }\`
28839
+
28840
+ ### addArtifact(options)
28841
+
28842
+ Uploads proof-of-work artifact.
28843
+
28844
+ **Parameters:**
28845
+ - \`planId\` (string) - Plan ID
28846
+ - \`sessionToken\` (string) - Session token
28847
+ - \`type\` ('screenshot' | 'video' | 'test_results' | 'diff')
28848
+ - \`filename\` (string) - File name
28849
+ - \`source\` ('file' | 'url' | 'base64')
28850
+ - \`filePath\` (string) - Local file path (when source='file')
28851
+ - \`deliverableId\` (string, optional) - Links artifact to deliverable
28852
+
28853
+ **Returns:** \`{ artifactId, url, allDeliverablesComplete, snapshotUrl? }\`
28854
+
28855
+ ### requestUserInput(options)
28856
+
28857
+ Asks user a question via browser modal.
28858
+
28859
+ **Parameters:**
28860
+ - \`message\` (string) - Question to ask
28861
+ - \`type\` (string) - Input type (see below)
28862
+ - \`options\` (string[], for 'choice') - Available choices
28863
+ - \`timeout\` (number, optional) - Timeout in seconds
28864
+ - Type-specific parameters (min, max, format, etc.)
28865
+
28866
+ **Returns:** \`{ success, response?, status }\`
28867
+
28868
+ **Supported types (8 total):**
28869
+ 1. \`text\` - Single-line text
28870
+ 2. \`multiline\` - Multi-line text area
28871
+ 3. \`choice\` - Radio/checkbox/dropdown (auto-adds "Other" option)
28872
+ - Auto-switches: 1-8 options = radio/checkbox, 9+ = dropdown
28873
+ - \`multiSelect: true\` for checkboxes
28874
+ - \`displayAs: 'dropdown'\` to force dropdown UI
28875
+ 4. \`confirm\` - Yes/No buttons
28876
+ 5. \`number\` - Numeric input with validation
28877
+ - \`min\`, \`max\`, \`format\` ('integer' | 'decimal' | 'currency' | 'percentage')
28878
+ 6. \`email\` - Email validation
28879
+ - \`domain\` for restriction
28880
+ 7. \`date\` - Date picker with range
28881
+ - \`minDate\`, \`maxDate\` (YYYY-MM-DD format)
28882
+ 8. \`rating\` - Scale rating (auto-selects stars/numbers)
28883
+ - \`min\`, \`max\`, \`style\` ('stars' | 'numbers' | 'emoji'), \`labels\`
28884
+
28885
+ **Response format:**
28886
+ - All responses are strings
28887
+ - choice (single): \`"PostgreSQL"\` or custom text from "Other"
28888
+ - choice (multi): \`"option1, option2"\` (comma-space separated)
28889
+ - confirm: \`"yes"\` or \`"no"\` (lowercase)
28890
+ - number: \`"42"\` or \`"3.14"\`
28891
+ - email: \`"user@example.com"\`
28892
+ - date: \`"2026-01-24"\` (ISO 8601)
28893
+ - rating: \`"4"\` (integer as string)
28894
+ - See docs/INPUT-RESPONSE-FORMATS.md for complete specification`;
28895
+ var HANDLING_FEEDBACK = `## Handling Reviewer Feedback
28896
+
28897
+ \`\`\`typescript
28898
+ const status = await readPlan(planId, sessionToken, {
28899
+ includeAnnotations: true
28900
+ });
28901
+
28902
+ if (status.status === "changes_requested") {
28903
+ // Read the content for inline comments
28904
+ console.log(status.content);
28905
+
28906
+ // Make changes based on feedback
28907
+ // Upload new artifacts
28908
+ // Plan will transition back to pending_review
28909
+ }
28910
+ \`\`\``;
28911
+ var MCP_DIRECT_INSTRUCTIONS = [
28912
+ MCP_DIRECT_HEADER,
28913
+ "",
28914
+ CRITICAL_USAGE_SECTION,
28915
+ "",
28916
+ USER_INPUT_SECTION,
28917
+ "",
28918
+ MCP_TOOLS_OVERVIEW,
28919
+ "",
28920
+ MCP_WORKFLOW,
28921
+ "",
28922
+ DELIVERABLES_SECTION,
28923
+ "",
28924
+ ARTIFACT_TYPES_SECTION,
28925
+ "",
28926
+ API_REFERENCE,
28927
+ "",
28928
+ HANDLING_FEEDBACK,
28929
+ "",
28930
+ TIPS_SECTION,
28931
+ "",
28932
+ WHEN_NOT_TO_USE_SECTION,
28933
+ "",
28934
+ TROUBLESHOOTING_SECTION
28935
+ ].join("\n");
28936
+
28937
+ // src/adapters/claude-code.ts
28938
+ init_cjs_shims();
28939
+
28940
+ // ../../packages/schema/dist/index.mjs
28941
+ init_cjs_shims();
28942
+
28943
+ // ../../packages/schema/dist/yjs-helpers-DxqhtEAu.mjs
28944
+ init_cjs_shims();
28945
+
28946
+ // ../../packages/schema/dist/plan.mjs
28947
+ init_cjs_shims();
28948
+
28949
+ // ../../node_modules/.pnpm/zod@4.3.5/node_modules/zod/index.js
28950
+ init_cjs_shims();
28951
+
28952
+ // ../../node_modules/.pnpm/zod@4.3.5/node_modules/zod/v4/classic/external.js
28953
+ var external_exports = {};
28954
+ __export(external_exports, {
28955
+ $brand: () => $brand,
28956
+ $input: () => $input,
28957
+ $output: () => $output,
28958
+ NEVER: () => NEVER,
28959
+ TimePrecision: () => TimePrecision,
28960
+ ZodAny: () => ZodAny,
28961
+ ZodArray: () => ZodArray,
28962
+ ZodBase64: () => ZodBase64,
28963
+ ZodBase64URL: () => ZodBase64URL,
28964
+ ZodBigInt: () => ZodBigInt,
28965
+ ZodBigIntFormat: () => ZodBigIntFormat,
28966
+ ZodBoolean: () => ZodBoolean,
28967
+ ZodCIDRv4: () => ZodCIDRv4,
28968
+ ZodCIDRv6: () => ZodCIDRv6,
28969
+ ZodCUID: () => ZodCUID,
28970
+ ZodCUID2: () => ZodCUID2,
28971
+ ZodCatch: () => ZodCatch,
28972
+ ZodCodec: () => ZodCodec,
28973
+ ZodCustom: () => ZodCustom,
28974
+ ZodCustomStringFormat: () => ZodCustomStringFormat,
28975
+ ZodDate: () => ZodDate,
28976
+ ZodDefault: () => ZodDefault,
28977
+ ZodDiscriminatedUnion: () => ZodDiscriminatedUnion,
28978
+ ZodE164: () => ZodE164,
28979
+ ZodEmail: () => ZodEmail,
28980
+ ZodEmoji: () => ZodEmoji,
28981
+ ZodEnum: () => ZodEnum,
28982
+ ZodError: () => ZodError,
28983
+ ZodExactOptional: () => ZodExactOptional,
28984
+ ZodFile: () => ZodFile,
28985
+ ZodFirstPartyTypeKind: () => ZodFirstPartyTypeKind,
28986
+ ZodFunction: () => ZodFunction,
28987
+ ZodGUID: () => ZodGUID,
28988
+ ZodIPv4: () => ZodIPv4,
28989
+ ZodIPv6: () => ZodIPv6,
28990
+ ZodISODate: () => ZodISODate,
28991
+ ZodISODateTime: () => ZodISODateTime,
28992
+ ZodISODuration: () => ZodISODuration,
28993
+ ZodISOTime: () => ZodISOTime,
28994
+ ZodIntersection: () => ZodIntersection,
28995
+ ZodIssueCode: () => ZodIssueCode,
28996
+ ZodJWT: () => ZodJWT,
28997
+ ZodKSUID: () => ZodKSUID,
28998
+ ZodLazy: () => ZodLazy,
28999
+ ZodLiteral: () => ZodLiteral,
29000
+ ZodMAC: () => ZodMAC,
29001
+ ZodMap: () => ZodMap,
29002
+ ZodNaN: () => ZodNaN,
29003
+ ZodNanoID: () => ZodNanoID,
29004
+ ZodNever: () => ZodNever,
29005
+ ZodNonOptional: () => ZodNonOptional,
29006
+ ZodNull: () => ZodNull,
29007
+ ZodNullable: () => ZodNullable,
29008
+ ZodNumber: () => ZodNumber,
29009
+ ZodNumberFormat: () => ZodNumberFormat,
29010
+ ZodObject: () => ZodObject,
29011
+ ZodOptional: () => ZodOptional,
29012
+ ZodPipe: () => ZodPipe,
29013
+ ZodPrefault: () => ZodPrefault,
29014
+ ZodPromise: () => ZodPromise,
29015
+ ZodReadonly: () => ZodReadonly,
29016
+ ZodRealError: () => ZodRealError,
29017
+ ZodRecord: () => ZodRecord,
29018
+ ZodSet: () => ZodSet,
29019
+ ZodString: () => ZodString,
29020
+ ZodStringFormat: () => ZodStringFormat,
29021
+ ZodSuccess: () => ZodSuccess,
29022
+ ZodSymbol: () => ZodSymbol,
29023
+ ZodTemplateLiteral: () => ZodTemplateLiteral,
29024
+ ZodTransform: () => ZodTransform,
29025
+ ZodTuple: () => ZodTuple,
29026
+ ZodType: () => ZodType,
29027
+ ZodULID: () => ZodULID,
29028
+ ZodURL: () => ZodURL,
29029
+ ZodUUID: () => ZodUUID,
29030
+ ZodUndefined: () => ZodUndefined,
29031
+ ZodUnion: () => ZodUnion,
29032
+ ZodUnknown: () => ZodUnknown,
29033
+ ZodVoid: () => ZodVoid,
29034
+ ZodXID: () => ZodXID,
29035
+ ZodXor: () => ZodXor,
29036
+ _ZodString: () => _ZodString,
29037
+ _default: () => _default2,
29038
+ _function: () => _function,
29039
+ any: () => any,
29040
+ array: () => array,
29041
+ base64: () => base642,
29042
+ base64url: () => base64url2,
29043
+ bigint: () => bigint2,
29044
+ boolean: () => boolean2,
29045
+ catch: () => _catch2,
29046
+ check: () => check,
29047
+ cidrv4: () => cidrv42,
29048
+ cidrv6: () => cidrv62,
29049
+ clone: () => clone,
29050
+ codec: () => codec,
29051
+ coerce: () => coerce_exports,
29052
+ config: () => config,
29053
+ core: () => core_exports2,
29054
+ cuid: () => cuid3,
29055
+ cuid2: () => cuid22,
29056
+ custom: () => custom,
29057
+ date: () => date3,
29058
+ decode: () => decode2,
29059
+ decodeAsync: () => decodeAsync2,
29060
+ describe: () => describe2,
29061
+ discriminatedUnion: () => discriminatedUnion,
29062
+ e164: () => e1642,
29063
+ email: () => email2,
29064
+ emoji: () => emoji2,
29065
+ encode: () => encode2,
29066
+ encodeAsync: () => encodeAsync2,
29067
+ endsWith: () => _endsWith,
29068
+ enum: () => _enum2,
29069
+ exactOptional: () => exactOptional,
29070
+ file: () => file,
29071
+ flattenError: () => flattenError,
29072
+ float32: () => float32,
29073
+ float64: () => float64,
29074
+ formatError: () => formatError,
29075
+ fromJSONSchema: () => fromJSONSchema,
29076
+ function: () => _function,
29077
+ getErrorMap: () => getErrorMap,
29078
+ globalRegistry: () => globalRegistry,
29079
+ gt: () => _gt,
29080
+ gte: () => _gte,
29081
+ guid: () => guid2,
29082
+ hash: () => hash,
29083
+ hex: () => hex2,
29084
+ hostname: () => hostname2,
29085
+ httpUrl: () => httpUrl,
29086
+ includes: () => _includes,
29087
+ instanceof: () => _instanceof,
29088
+ int: () => int,
29089
+ int32: () => int32,
29090
+ int64: () => int64,
29091
+ intersection: () => intersection,
29092
+ ipv4: () => ipv42,
29093
+ ipv6: () => ipv62,
29094
+ iso: () => iso_exports,
29095
+ json: () => json,
29096
+ jwt: () => jwt,
29097
+ keyof: () => keyof,
29098
+ ksuid: () => ksuid2,
29099
+ lazy: () => lazy,
29100
+ length: () => _length,
29101
+ literal: () => literal,
29102
+ locales: () => locales_exports,
29103
+ looseObject: () => looseObject,
29104
+ looseRecord: () => looseRecord,
29105
+ lowercase: () => _lowercase,
29106
+ lt: () => _lt,
29107
+ lte: () => _lte,
29108
+ mac: () => mac2,
29109
+ map: () => map,
29110
+ maxLength: () => _maxLength,
29111
+ maxSize: () => _maxSize,
29112
+ meta: () => meta2,
29113
+ mime: () => _mime,
29114
+ minLength: () => _minLength,
29115
+ minSize: () => _minSize,
29116
+ multipleOf: () => _multipleOf,
29117
+ nan: () => nan,
29118
+ nanoid: () => nanoid2,
29119
+ nativeEnum: () => nativeEnum,
29120
+ negative: () => _negative,
29121
+ never: () => never,
29122
+ nonnegative: () => _nonnegative,
29123
+ nonoptional: () => nonoptional,
29124
+ nonpositive: () => _nonpositive,
29125
+ normalize: () => _normalize,
29126
+ null: () => _null3,
29127
+ nullable: () => nullable,
29128
+ nullish: () => nullish2,
29129
+ number: () => number2,
29130
+ object: () => object,
29131
+ optional: () => optional,
29132
+ overwrite: () => _overwrite,
29133
+ parse: () => parse2,
29134
+ parseAsync: () => parseAsync2,
29135
+ partialRecord: () => partialRecord,
29136
+ pipe: () => pipe,
29137
+ positive: () => _positive,
29138
+ prefault: () => prefault,
29139
+ preprocess: () => preprocess,
29140
+ prettifyError: () => prettifyError,
29141
+ promise: () => promise,
29142
+ property: () => _property,
29143
+ readonly: () => readonly,
29144
+ record: () => record,
29145
+ refine: () => refine,
29146
+ regex: () => _regex,
29147
+ regexes: () => regexes_exports,
29148
+ registry: () => registry,
29149
+ safeDecode: () => safeDecode2,
29150
+ safeDecodeAsync: () => safeDecodeAsync2,
29151
+ safeEncode: () => safeEncode2,
29152
+ safeEncodeAsync: () => safeEncodeAsync2,
29153
+ safeParse: () => safeParse2,
29154
+ safeParseAsync: () => safeParseAsync2,
29155
+ set: () => set,
29156
+ setErrorMap: () => setErrorMap,
29157
+ size: () => _size,
29158
+ slugify: () => _slugify,
29159
+ startsWith: () => _startsWith,
29160
+ strictObject: () => strictObject,
28715
29161
  string: () => string2,
28716
29162
  stringFormat: () => stringFormat,
28717
29163
  stringbool: () => stringbool,
@@ -42541,7 +42987,8 @@ var PlanEventSchema = external_exports.discriminatedUnion("type", [
42541
42987
  "multi"
42542
42988
  ]),
42543
42989
  requestMessage: external_exports.string().optional(),
42544
- questionCount: external_exports.number().optional()
42990
+ questionCount: external_exports.number().optional(),
42991
+ isBlocker: external_exports.boolean().optional()
42545
42992
  })
42546
42993
  }),
42547
42994
  PlanEventBaseSchema.extend({
@@ -42672,7 +43119,7 @@ var PRReviewCommentSchema = external_exports.object({
42672
43119
  resolved: external_exports.boolean().optional()
42673
43120
  });
42674
43121
 
42675
- // ../../packages/schema/dist/yjs-helpers-Dg3vErAn.mjs
43122
+ // ../../packages/schema/dist/yjs-helpers-DxqhtEAu.mjs
42676
43123
  function assertNever2(value) {
42677
43124
  throw new Error(`Unhandled discriminated union member: ${JSON.stringify(value)}`);
42678
43125
  }
@@ -42781,7 +43228,8 @@ var InputRequestBaseSchema = external_exports.object({
42781
43228
  planId: external_exports.string().optional(),
42782
43229
  response: external_exports.unknown().optional(),
42783
43230
  answeredAt: external_exports.number().optional(),
42784
- answeredBy: external_exports.string().optional()
43231
+ answeredBy: external_exports.string().optional(),
43232
+ isBlocker: external_exports.boolean().optional()
42785
43233
  });
42786
43234
  var TextInputSchema = InputRequestBaseSchema.extend({ type: external_exports.literal("text") });
42787
43235
  var MultilineInputSchema = InputRequestBaseSchema.extend({ type: external_exports.literal("multiline") });
@@ -42927,7 +43375,8 @@ var MultiQuestionInputRequestSchema = external_exports.object({
42927
43375
  planId: external_exports.string().optional(),
42928
43376
  responses: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
42929
43377
  answeredAt: external_exports.number().optional(),
42930
- answeredBy: external_exports.string().optional()
43378
+ answeredBy: external_exports.string().optional(),
43379
+ isBlocker: external_exports.boolean().optional()
42931
43380
  });
42932
43381
  var AnyInputRequestSchema = external_exports.union([InputRequestSchema, MultiQuestionInputRequestSchema]);
42933
43382
  var YDOC_KEYS = {
@@ -43792,934 +44241,500 @@ var A2APartSchema = external_exports.object({ type: external_exports.enum([
43792
44241
  "file"
43793
44242
  ]) }).passthrough().superRefine((val, ctx) => {
43794
44243
  if (val.type === "text") {
43795
- if (typeof val.text !== "string") ctx.addIssue({
43796
- code: external_exports.ZodIssueCode.custom,
43797
- message: "text part must have a string text field"
43798
- });
43799
- } else if (val.type === "data") {
43800
- if (!("data" in val)) ctx.addIssue({
43801
- code: external_exports.ZodIssueCode.custom,
43802
- message: "data part must have a data field"
43803
- });
43804
- } else if (val.type === "file") {
43805
- if (typeof val.uri !== "string") ctx.addIssue({
43806
- code: external_exports.ZodIssueCode.custom,
43807
- message: "file part must have a string uri field"
43808
- });
43809
- }
43810
- });
43811
- function isValidA2APart(part) {
43812
- if (!part || typeof part !== "object") return false;
43813
- const p = part;
43814
- const t$1 = p.type;
43815
- if (t$1 === "text") return typeof p.text === "string";
43816
- else if (t$1 === "data") return "data" in p;
43817
- else if (t$1 === "file") return typeof p.uri === "string";
43818
- return false;
43819
- }
43820
- function isValidA2AParts(parts) {
43821
- if (!Array.isArray(parts)) return false;
43822
- return parts.every(isValidA2APart);
43823
- }
43824
- var A2AMessageSchema = external_exports.object({
43825
- messageId: external_exports.string(),
43826
- role: external_exports.enum(["user", "agent"]),
43827
- contextId: external_exports.string().optional(),
43828
- taskId: external_exports.string().optional(),
43829
- referenceTaskIds: external_exports.array(external_exports.string()).optional(),
43830
- metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
43831
- extensions: external_exports.array(external_exports.string()).optional()
43832
- }).passthrough().refine((val) => {
43833
- const parts = val.parts;
43834
- return isValidA2AParts(parts);
43835
- }, {
43836
- message: "Invalid parts array - each part must have valid type and required fields",
43837
- path: ["parts"]
43838
- }).transform((val) => ({
43839
- ...val,
43840
- parts: val.parts
43841
- }));
43842
- var ConversationExportMetaSchema = external_exports.object({
43843
- exportId: external_exports.string(),
43844
- sourcePlatform: external_exports.string(),
43845
- sourceSessionId: external_exports.string(),
43846
- planId: external_exports.string(),
43847
- exportedAt: external_exports.number(),
43848
- messageCount: external_exports.number(),
43849
- compressedBytes: external_exports.number(),
43850
- uncompressedBytes: external_exports.number()
43851
- });
43852
- external_exports.object({
43853
- type: external_exports.literal("text"),
43854
- text: external_exports.string()
43855
- });
43856
- external_exports.object({
43857
- type: external_exports.literal("tool_use"),
43858
- id: external_exports.string(),
43859
- name: external_exports.string(),
43860
- input: external_exports.record(external_exports.string(), external_exports.unknown())
43861
- });
43862
- external_exports.object({
43863
- type: external_exports.literal("tool_result"),
43864
- tool_use_id: external_exports.string(),
43865
- content: external_exports.unknown(),
43866
- is_error: external_exports.boolean().optional()
43867
- });
43868
- var ClaudeCodeContentBlockSchema = external_exports.object({ type: external_exports.enum([
43869
- "text",
43870
- "tool_use",
43871
- "tool_result"
43872
- ]) }).passthrough().superRefine((val, ctx) => {
43873
- const typedVal = val;
43874
- if (val.type === "text") {
43875
- if (typeof typedVal.text !== "string") ctx.addIssue({
43876
- code: external_exports.ZodIssueCode.custom,
43877
- message: "text block must have a string text field"
43878
- });
43879
- } else if (val.type === "tool_use") {
43880
- if (typeof typedVal.id !== "string") ctx.addIssue({
43881
- code: external_exports.ZodIssueCode.custom,
43882
- message: "tool_use block must have a string id field"
43883
- });
43884
- if (typeof typedVal.name !== "string") ctx.addIssue({
44244
+ if (typeof val.text !== "string") ctx.addIssue({
43885
44245
  code: external_exports.ZodIssueCode.custom,
43886
- message: "tool_use block must have a string name field"
44246
+ message: "text part must have a string text field"
43887
44247
  });
43888
- if (typeof typedVal.input !== "object" || typedVal.input === null) ctx.addIssue({
44248
+ } else if (val.type === "data") {
44249
+ if (!("data" in val)) ctx.addIssue({
43889
44250
  code: external_exports.ZodIssueCode.custom,
43890
- message: "tool_use block must have an object input field"
44251
+ message: "data part must have a data field"
43891
44252
  });
43892
- } else if (val.type === "tool_result") {
43893
- if (typeof typedVal.tool_use_id !== "string") ctx.addIssue({
44253
+ } else if (val.type === "file") {
44254
+ if (typeof val.uri !== "string") ctx.addIssue({
43894
44255
  code: external_exports.ZodIssueCode.custom,
43895
- message: "tool_result block must have a string tool_use_id field"
44256
+ message: "file part must have a string uri field"
43896
44257
  });
43897
44258
  }
43898
44259
  });
43899
- var ClaudeCodeUsageSchema = external_exports.object({
43900
- input_tokens: external_exports.number(),
43901
- output_tokens: external_exports.number(),
43902
- cache_creation_input_tokens: external_exports.number().optional(),
43903
- cache_read_input_tokens: external_exports.number().optional()
43904
- });
43905
- var ClaudeCodeMessageInnerSchema = external_exports.object({
43906
- role: external_exports.string(),
43907
- content: external_exports.array(ClaudeCodeContentBlockSchema),
43908
- id: external_exports.string().optional(),
43909
- model: external_exports.string().optional(),
43910
- usage: ClaudeCodeUsageSchema.optional()
43911
- });
43912
- var ClaudeCodeMessageSchema = external_exports.object({
43913
- sessionId: external_exports.string(),
43914
- type: external_exports.enum([
43915
- "user",
43916
- "assistant",
43917
- "summary"
43918
- ]),
43919
- message: ClaudeCodeMessageInnerSchema,
43920
- uuid: external_exports.string(),
43921
- timestamp: external_exports.string(),
43922
- parentUuid: external_exports.string().optional(),
43923
- costUSD: external_exports.number().optional(),
43924
- durationMs: external_exports.number().optional()
43925
- });
43926
- var GitHubPRResponseSchema = external_exports.object({
43927
- number: external_exports.number(),
43928
- html_url: external_exports.string().url(),
43929
- title: external_exports.string(),
43930
- state: external_exports.enum(["open", "closed"]),
43931
- draft: external_exports.boolean(),
43932
- merged: external_exports.boolean(),
43933
- head: external_exports.object({ ref: external_exports.string() })
43934
- });
43935
- var ROUTES = {
43936
- REGISTRY_LIST: "/registry",
43937
- REGISTRY_REGISTER: "/register",
43938
- REGISTRY_UNREGISTER: "/unregister",
43939
- PLAN_STATUS: (planId) => `/api/plan/${planId}/status`,
43940
- PLAN_HAS_CONNECTIONS: (planId) => `/api/plan/${planId}/has-connections`,
43941
- PLAN_TRANSCRIPT: (planId) => `/api/plan/${planId}/transcript`,
43942
- PLAN_SUBSCRIBE: (planId) => `/api/plan/${planId}/subscribe`,
43943
- PLAN_CHANGES: (planId) => `/api/plan/${planId}/changes`,
43944
- PLAN_UNSUBSCRIBE: (planId) => `/api/plan/${planId}/unsubscribe`,
43945
- PLAN_PR_DIFF: (planId, prNumber) => `/api/plans/${planId}/pr-diff/${prNumber}`,
43946
- PLAN_PR_FILES: (planId, prNumber) => `/api/plans/${planId}/pr-files/${prNumber}`,
43947
- HOOK_SESSION: "/api/hook/session",
43948
- HOOK_CONTENT: (planId) => `/api/hook/plan/${planId}/content`,
43949
- HOOK_REVIEW: (planId) => `/api/hook/plan/${planId}/review`,
43950
- HOOK_SESSION_TOKEN: (planId) => `/api/hook/plan/${planId}/session-token`,
43951
- HOOK_PRESENCE: (planId) => `/api/hook/plan/${planId}/presence`,
43952
- CONVERSATION_IMPORT: "/api/conversation/import",
43953
- WEB_TASK: (planId) => `/task/${planId}`
43954
- };
43955
- function createPlanWebUrl(baseUrl, planId) {
43956
- return `${baseUrl.replace(/\/$/, "")}${ROUTES.WEB_TASK(planId)}`;
44260
+ function isValidA2APart(part) {
44261
+ if (!part || typeof part !== "object") return false;
44262
+ const p = part;
44263
+ const t$1 = p.type;
44264
+ if (t$1 === "text") return typeof p.text === "string";
44265
+ else if (t$1 === "data") return "data" in p;
44266
+ else if (t$1 === "file") return typeof p.uri === "string";
44267
+ return false;
43957
44268
  }
43958
- var InviteTokenSchema = external_exports.object({
43959
- id: external_exports.string(),
43960
- tokenHash: external_exports.string(),
43961
- planId: external_exports.string(),
43962
- createdBy: external_exports.string(),
43963
- createdAt: external_exports.number(),
43964
- expiresAt: external_exports.number(),
43965
- maxUses: external_exports.number().nullable(),
43966
- useCount: external_exports.number(),
43967
- revoked: external_exports.boolean(),
43968
- label: external_exports.string().optional()
43969
- });
43970
- var InviteRedemptionSchema = external_exports.object({
43971
- redeemedBy: external_exports.string(),
43972
- redeemedAt: external_exports.number(),
43973
- tokenId: external_exports.string()
43974
- });
43975
- var GitFileStatusSchema = external_exports.enum([
43976
- "added",
43977
- "modified",
43978
- "deleted",
43979
- "renamed",
43980
- "copied",
43981
- "untracked"
43982
- ]);
43983
- var LocalFileChangeSchema = external_exports.object({
43984
- path: external_exports.string(),
43985
- status: GitFileStatusSchema,
43986
- additions: external_exports.number(),
43987
- deletions: external_exports.number(),
43988
- patch: external_exports.string().optional()
43989
- });
43990
- var LocalChangesResponseSchema = external_exports.object({
43991
- available: external_exports.literal(true),
43992
- branch: external_exports.string(),
43993
- baseBranch: external_exports.string(),
43994
- staged: external_exports.array(LocalFileChangeSchema),
43995
- unstaged: external_exports.array(LocalFileChangeSchema),
43996
- untracked: external_exports.array(external_exports.string()),
43997
- files: external_exports.array(LocalFileChangeSchema)
43998
- });
43999
- var LocalChangesUnavailableReasonSchema = external_exports.enum([
44000
- "no_cwd",
44001
- "not_git_repo",
44002
- "mcp_not_connected",
44003
- "git_error"
44004
- ]);
44005
- var LocalChangesUnavailableSchema = external_exports.object({
44006
- available: external_exports.literal(false),
44007
- reason: LocalChangesUnavailableReasonSchema,
44008
- message: external_exports.string()
44009
- });
44010
- var LocalChangesResultSchema = external_exports.discriminatedUnion("available", [LocalChangesResponseSchema, LocalChangesUnavailableSchema]);
44011
- var ConversationExportStartMetaSchema = external_exports.object({
44269
+ function isValidA2AParts(parts) {
44270
+ if (!Array.isArray(parts)) return false;
44271
+ return parts.every(isValidA2APart);
44272
+ }
44273
+ var A2AMessageSchema = external_exports.object({
44274
+ messageId: external_exports.string(),
44275
+ role: external_exports.enum(["user", "agent"]),
44276
+ contextId: external_exports.string().optional(),
44277
+ taskId: external_exports.string().optional(),
44278
+ referenceTaskIds: external_exports.array(external_exports.string()).optional(),
44279
+ metadata: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
44280
+ extensions: external_exports.array(external_exports.string()).optional()
44281
+ }).passthrough().refine((val) => {
44282
+ const parts = val.parts;
44283
+ return isValidA2AParts(parts);
44284
+ }, {
44285
+ message: "Invalid parts array - each part must have valid type and required fields",
44286
+ path: ["parts"]
44287
+ }).transform((val) => ({
44288
+ ...val,
44289
+ parts: val.parts
44290
+ }));
44291
+ var ConversationExportMetaSchema = external_exports.object({
44012
44292
  exportId: external_exports.string(),
44013
- totalChunks: external_exports.number().int().positive(),
44014
- totalBytes: external_exports.number().int().nonnegative(),
44015
- compressedBytes: external_exports.number().int().nonnegative(),
44016
44293
  sourcePlatform: external_exports.string(),
44017
44294
  sourceSessionId: external_exports.string(),
44018
44295
  planId: external_exports.string(),
44019
- exportedAt: external_exports.number().int().positive()
44020
- });
44021
- var ChunkMessageSchema = external_exports.object({
44022
- exportId: external_exports.string(),
44023
- chunkIndex: external_exports.number().int().nonnegative(),
44024
- data: external_exports.instanceof(Uint8Array)
44025
- });
44026
- var ConversationExportEndSchema = external_exports.object({
44027
- exportId: external_exports.string(),
44028
- checksum: external_exports.string()
44029
- });
44030
- var textEncoder = new TextEncoder();
44031
- var textDecoder = new TextDecoder();
44032
- var PlanIndexEntrySchema = external_exports.discriminatedUnion("deleted", [external_exports.object({
44033
- deleted: external_exports.literal(false),
44034
- id: external_exports.string(),
44035
- title: external_exports.string(),
44036
- status: external_exports.enum(PlanStatusValues),
44037
- createdAt: external_exports.number(),
44038
- updatedAt: external_exports.number(),
44039
- ownerId: external_exports.string(),
44040
- tags: external_exports.array(external_exports.string()).optional()
44041
- }), external_exports.object({
44042
- deleted: external_exports.literal(true),
44043
- id: external_exports.string(),
44044
- title: external_exports.string(),
44045
- status: external_exports.enum(PlanStatusValues),
44046
- createdAt: external_exports.number(),
44047
- updatedAt: external_exports.number(),
44048
- ownerId: external_exports.string(),
44049
- tags: external_exports.array(external_exports.string()).optional(),
44050
- deletedAt: external_exports.number(),
44051
- deletedBy: external_exports.string()
44052
- })]);
44053
- function formatThreadsForLLM(threads, options = {}) {
44054
- const { includeResolved = false, selectedTextMaxLength = 100, resolveUser } = options;
44055
- const unresolvedThreads = threads.filter((t$1) => !t$1.resolved);
44056
- const resolvedCount = threads.length - unresolvedThreads.length;
44057
- const threadsToShow = includeResolved ? threads : unresolvedThreads;
44058
- if (threadsToShow.length === 0) {
44059
- if (resolvedCount > 0) return `All ${resolvedCount} comment(s) have been resolved.`;
44060
- return "";
44061
- }
44062
- let output = threadsToShow.map((thread, index) => {
44063
- const location = thread.selectedText ? `On: "${truncate(thread.selectedText, selectedTextMaxLength)}"` : `Comment ${index + 1}`;
44064
- const comments = thread.comments.map((c, idx) => {
44065
- const text = extractTextFromCommentBody(c.body);
44066
- const author = resolveUser ? resolveUser(c.userId) : c.userId.slice(0, 8);
44067
- if (idx === 0) return `${author}: ${text}`;
44068
- return `${author} (reply): ${text}`;
44069
- }).join("\n");
44070
- return `${location}${thread.resolved ? " [Resolved]" : ""}
44071
- ${comments}`;
44072
- }).join("\n\n");
44073
- if (!includeResolved && resolvedCount > 0) output += `
44074
-
44075
- ---
44076
- (${resolvedCount} resolved comment(s) not shown)`;
44077
- return output;
44078
- }
44079
- function truncate(text, maxLength) {
44080
- const cleaned = text.replace(/\n/g, " ").trim();
44081
- if (cleaned.length <= maxLength) return cleaned;
44082
- return `${cleaned.slice(0, maxLength)}...`;
44083
- }
44084
- var TOOL_NAMES = {
44085
- ADD_ARTIFACT: "add_artifact",
44086
- ADD_PR_REVIEW_COMMENT: "add_pr_review_comment",
44087
- COMPLETE_TASK: "complete_task",
44088
- CREATE_PLAN: "create_plan",
44089
- EXECUTE_CODE: "execute_code",
44090
- LINK_PR: "link_pr",
44091
- READ_PLAN: "read_plan",
44092
- REGENERATE_SESSION_TOKEN: "regenerate_session_token",
44093
- REQUEST_USER_INPUT: "request_user_input",
44094
- SETUP_REVIEW_NOTIFICATION: "setup_review_notification",
44095
- UPDATE_BLOCK_CONTENT: "update_block_content",
44096
- UPDATE_PLAN: "update_plan"
44097
- };
44098
- var PlanIdSchema = external_exports.object({ planId: external_exports.string().min(1) });
44099
- var PlanStatusResponseSchema = external_exports.object({ status: external_exports.string() });
44100
- var HasConnectionsResponseSchema = external_exports.object({ hasConnections: external_exports.boolean() });
44101
- var SubscriptionClientIdSchema = external_exports.object({
44102
- planId: external_exports.string().min(1),
44103
- clientId: external_exports.string().min(1)
44296
+ exportedAt: external_exports.number(),
44297
+ messageCount: external_exports.number(),
44298
+ compressedBytes: external_exports.number(),
44299
+ uncompressedBytes: external_exports.number()
44104
44300
  });
44105
- var ChangeTypeSchema = external_exports.enum([
44106
- "status",
44107
- "comments",
44108
- "resolved",
44109
- "content",
44110
- "artifacts"
44111
- ]);
44112
- var ChangeSchema = external_exports.object({
44113
- type: ChangeTypeSchema,
44114
- timestamp: external_exports.number(),
44115
- summary: external_exports.string(),
44116
- details: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
44301
+ external_exports.object({
44302
+ type: external_exports.literal("text"),
44303
+ text: external_exports.string()
44117
44304
  });
44118
- var ChangesResponseSchema = external_exports.discriminatedUnion("ready", [external_exports.object({
44119
- ready: external_exports.literal(true),
44120
- changes: external_exports.string(),
44121
- details: external_exports.array(ChangeSchema)
44122
- }), external_exports.object({
44123
- ready: external_exports.literal(false),
44124
- pending: external_exports.number(),
44125
- windowExpiresIn: external_exports.number()
44126
- })]);
44127
- var DeleteSubscriptionResponseSchema = external_exports.object({ success: external_exports.boolean() });
44128
- var SetSessionTokenRequestSchema = external_exports.object({ sessionTokenHash: external_exports.string().min(1) });
44129
- var GetDeliverableContextRequestSchema = external_exports.object({ sessionToken: external_exports.string().min(1) });
44130
- var GetDeliverableContextResponseSchema = external_exports.object({ context: external_exports.string() });
44131
- var SetSessionTokenResponseSchema = external_exports.object({ url: external_exports.string() });
44132
- var ImportConversationRequestSchema = external_exports.object({
44133
- a2aMessages: external_exports.array(A2AMessageSchema),
44134
- meta: external_exports.object({
44135
- planId: external_exports.string().optional(),
44136
- sourcePlatform: external_exports.string().optional(),
44137
- sessionId: external_exports.string().optional()
44138
- }).optional()
44305
+ external_exports.object({
44306
+ type: external_exports.literal("tool_use"),
44307
+ id: external_exports.string(),
44308
+ name: external_exports.string(),
44309
+ input: external_exports.record(external_exports.string(), external_exports.unknown())
44139
44310
  });
44140
- var ImportConversationResponseSchema = external_exports.discriminatedUnion("success", [external_exports.object({
44141
- success: external_exports.literal(true),
44142
- sessionId: external_exports.string(),
44143
- transcriptPath: external_exports.string(),
44144
- messageCount: external_exports.number()
44145
- }), external_exports.object({
44146
- success: external_exports.literal(false),
44147
- error: external_exports.string()
44148
- })]);
44149
- var t = initTRPC.context().create({ allowOutsideOfServer: true });
44150
- var router = t.router;
44151
- var publicProcedure = t.procedure;
44152
- var middleware = t.middleware;
44153
- var conversationRouter = router({ import: publicProcedure.input(ImportConversationRequestSchema).output(ImportConversationResponseSchema).mutation(async ({ input, ctx }) => {
44154
- return ctx.conversationHandlers.importConversation(input, ctx);
44155
- }) });
44156
- var hookRouter = router({
44157
- createSession: publicProcedure.input(CreateHookSessionRequestSchema).output(CreateHookSessionResponseSchema).mutation(async ({ input, ctx }) => {
44158
- return ctx.hookHandlers.createSession(input, ctx);
44159
- }),
44160
- updateContent: publicProcedure.input(PlanIdSchema.merge(UpdatePlanContentRequestSchema)).output(UpdatePlanContentResponseSchema).mutation(async ({ input, ctx }) => {
44161
- const { planId, ...contentInput } = input;
44162
- return ctx.hookHandlers.updateContent(planId, contentInput, ctx);
44163
- }),
44164
- getReviewStatus: publicProcedure.input(PlanIdSchema).output(GetReviewStatusResponseSchema).query(async ({ input, ctx }) => {
44165
- return ctx.hookHandlers.getReviewStatus(input.planId, ctx);
44166
- }),
44167
- updatePresence: publicProcedure.input(PlanIdSchema.merge(UpdatePresenceRequestSchema)).output(UpdatePresenceResponseSchema).mutation(async ({ input, ctx }) => {
44168
- const { planId, ...presenceInput } = input;
44169
- return ctx.hookHandlers.updatePresence(planId, presenceInput, ctx);
44170
- }),
44171
- setSessionToken: publicProcedure.input(PlanIdSchema.merge(SetSessionTokenRequestSchema)).output(SetSessionTokenResponseSchema).mutation(async ({ input, ctx }) => {
44172
- const { planId, sessionTokenHash } = input;
44173
- return ctx.hookHandlers.setSessionToken(planId, sessionTokenHash, ctx);
44174
- }),
44175
- waitForApproval: publicProcedure.input(external_exports.object({
44176
- planId: external_exports.string(),
44177
- reviewRequestId: external_exports.string()
44178
- })).output(external_exports.object({
44179
- approved: external_exports.boolean(),
44180
- feedback: external_exports.string().optional(),
44181
- deliverables: external_exports.array(external_exports.any()).optional(),
44182
- reviewComment: external_exports.string().optional(),
44183
- reviewedBy: external_exports.string().optional(),
44184
- status: external_exports.string().optional()
44185
- })).mutation(async ({ input, ctx }) => {
44186
- const { planId, reviewRequestId } = input;
44187
- return ctx.hookHandlers.waitForApproval(planId, reviewRequestId, ctx);
44188
- }),
44189
- getDeliverableContext: publicProcedure.input(PlanIdSchema.merge(GetDeliverableContextRequestSchema)).output(GetDeliverableContextResponseSchema).query(async ({ input, ctx }) => {
44190
- const { planId, sessionToken } = input;
44191
- return ctx.hookHandlers.getDeliverableContext(planId, sessionToken, ctx);
44192
- }),
44193
- getSessionContext: publicProcedure.input(external_exports.object({ sessionId: external_exports.string() })).output(external_exports.discriminatedUnion("found", [external_exports.object({
44194
- found: external_exports.literal(true),
44195
- planId: external_exports.string(),
44196
- sessionToken: external_exports.string(),
44197
- url: external_exports.string(),
44198
- deliverables: external_exports.array(external_exports.object({
44199
- id: external_exports.string(),
44200
- text: external_exports.string()
44201
- })),
44202
- reviewComment: external_exports.string().optional(),
44203
- reviewedBy: external_exports.string().optional(),
44204
- reviewStatus: external_exports.string().optional()
44205
- }), external_exports.object({ found: external_exports.literal(false) })])).query(async ({ input, ctx }) => {
44206
- return ctx.hookHandlers.getSessionContext(input.sessionId, ctx);
44207
- })
44311
+ external_exports.object({
44312
+ type: external_exports.literal("tool_result"),
44313
+ tool_use_id: external_exports.string(),
44314
+ content: external_exports.unknown(),
44315
+ is_error: external_exports.boolean().optional()
44208
44316
  });
44209
- var planRouter = router({
44210
- getStatus: publicProcedure.input(PlanIdSchema).output(PlanStatusResponseSchema).query(async ({ input, ctx }) => {
44211
- const metadata = getPlanMetadata(await ctx.getOrCreateDoc(input.planId));
44212
- if (!metadata) throw new TRPCError({
44213
- code: "NOT_FOUND",
44214
- message: "Plan not found"
44317
+ var ClaudeCodeContentBlockSchema = external_exports.object({ type: external_exports.enum([
44318
+ "text",
44319
+ "tool_use",
44320
+ "tool_result"
44321
+ ]) }).passthrough().superRefine((val, ctx) => {
44322
+ const typedVal = val;
44323
+ if (val.type === "text") {
44324
+ if (typeof typedVal.text !== "string") ctx.addIssue({
44325
+ code: external_exports.ZodIssueCode.custom,
44326
+ message: "text block must have a string text field"
44215
44327
  });
44216
- return { status: metadata.status };
44217
- }),
44218
- hasConnections: publicProcedure.input(PlanIdSchema).output(HasConnectionsResponseSchema).query(async ({ input, ctx }) => {
44219
- return { hasConnections: await ctx.getPlanStore().hasActiveConnections(input.planId) };
44220
- }),
44221
- getLocalChanges: publicProcedure.input(PlanIdSchema).output(LocalChangesResultSchema).query(async ({ input, ctx }) => {
44222
- const metadata = getPlanMetadata(await ctx.getOrCreateDoc(input.planId));
44223
- if (!metadata) throw new TRPCError({
44224
- code: "NOT_FOUND",
44225
- message: "Plan not found"
44328
+ } else if (val.type === "tool_use") {
44329
+ if (typeof typedVal.id !== "string") ctx.addIssue({
44330
+ code: external_exports.ZodIssueCode.custom,
44331
+ message: "tool_use block must have a string id field"
44226
44332
  });
44227
- const origin = metadata.origin;
44228
- const cwd = origin?.platform === "claude-code" ? origin.cwd : void 0;
44229
- if (!cwd) return {
44230
- available: false,
44231
- reason: "no_cwd",
44232
- message: "Plan has no associated working directory. Local changes are only available for plans created with working directory metadata."
44233
- };
44234
- return ctx.getLocalChanges(cwd);
44235
- }),
44236
- getFileContent: publicProcedure.input(external_exports.object({
44237
- planId: PlanIdSchema.shape.planId,
44238
- filePath: external_exports.string()
44239
- })).output(external_exports.object({
44240
- content: external_exports.string().nullable(),
44241
- error: external_exports.string().optional()
44242
- })).query(async ({ input, ctx }) => {
44243
- const metadata = getPlanMetadata(await ctx.getOrCreateDoc(input.planId));
44244
- if (!metadata) throw new TRPCError({
44245
- code: "NOT_FOUND",
44246
- message: "Plan not found"
44333
+ if (typeof typedVal.name !== "string") ctx.addIssue({
44334
+ code: external_exports.ZodIssueCode.custom,
44335
+ message: "tool_use block must have a string name field"
44247
44336
  });
44248
- const origin = metadata.origin;
44249
- const cwd = origin?.platform === "claude-code" ? origin.cwd : void 0;
44250
- if (!cwd) return {
44251
- content: null,
44252
- error: "No working directory available"
44253
- };
44254
- return ctx.getFileContent(cwd, input.filePath);
44255
- })
44337
+ if (typeof typedVal.input !== "object" || typedVal.input === null) ctx.addIssue({
44338
+ code: external_exports.ZodIssueCode.custom,
44339
+ message: "tool_use block must have an object input field"
44340
+ });
44341
+ } else if (val.type === "tool_result") {
44342
+ if (typeof typedVal.tool_use_id !== "string") ctx.addIssue({
44343
+ code: external_exports.ZodIssueCode.custom,
44344
+ message: "tool_result block must have a string tool_use_id field"
44345
+ });
44346
+ }
44347
+ });
44348
+ var ClaudeCodeUsageSchema = external_exports.object({
44349
+ input_tokens: external_exports.number(),
44350
+ output_tokens: external_exports.number(),
44351
+ cache_creation_input_tokens: external_exports.number().optional(),
44352
+ cache_read_input_tokens: external_exports.number().optional()
44353
+ });
44354
+ var ClaudeCodeMessageInnerSchema = external_exports.object({
44355
+ role: external_exports.string(),
44356
+ content: external_exports.array(ClaudeCodeContentBlockSchema),
44357
+ id: external_exports.string().optional(),
44358
+ model: external_exports.string().optional(),
44359
+ usage: ClaudeCodeUsageSchema.optional()
44360
+ });
44361
+ var ClaudeCodeMessageSchema = external_exports.object({
44362
+ sessionId: external_exports.string(),
44363
+ type: external_exports.enum([
44364
+ "user",
44365
+ "assistant",
44366
+ "summary"
44367
+ ]),
44368
+ message: ClaudeCodeMessageInnerSchema,
44369
+ uuid: external_exports.string(),
44370
+ timestamp: external_exports.string(),
44371
+ parentUuid: external_exports.string().optional(),
44372
+ costUSD: external_exports.number().optional(),
44373
+ durationMs: external_exports.number().optional()
44374
+ });
44375
+ var GitHubPRResponseSchema = external_exports.object({
44376
+ number: external_exports.number(),
44377
+ html_url: external_exports.string().url(),
44378
+ title: external_exports.string(),
44379
+ state: external_exports.enum(["open", "closed"]),
44380
+ draft: external_exports.boolean(),
44381
+ merged: external_exports.boolean(),
44382
+ head: external_exports.object({ ref: external_exports.string() })
44383
+ });
44384
+ var ROUTES = {
44385
+ REGISTRY_LIST: "/registry",
44386
+ REGISTRY_REGISTER: "/register",
44387
+ REGISTRY_UNREGISTER: "/unregister",
44388
+ PLAN_STATUS: (planId) => `/api/plan/${planId}/status`,
44389
+ PLAN_HAS_CONNECTIONS: (planId) => `/api/plan/${planId}/has-connections`,
44390
+ PLAN_TRANSCRIPT: (planId) => `/api/plan/${planId}/transcript`,
44391
+ PLAN_SUBSCRIBE: (planId) => `/api/plan/${planId}/subscribe`,
44392
+ PLAN_CHANGES: (planId) => `/api/plan/${planId}/changes`,
44393
+ PLAN_UNSUBSCRIBE: (planId) => `/api/plan/${planId}/unsubscribe`,
44394
+ PLAN_PR_DIFF: (planId, prNumber) => `/api/plans/${planId}/pr-diff/${prNumber}`,
44395
+ PLAN_PR_FILES: (planId, prNumber) => `/api/plans/${planId}/pr-files/${prNumber}`,
44396
+ HOOK_SESSION: "/api/hook/session",
44397
+ HOOK_CONTENT: (planId) => `/api/hook/plan/${planId}/content`,
44398
+ HOOK_REVIEW: (planId) => `/api/hook/plan/${planId}/review`,
44399
+ HOOK_SESSION_TOKEN: (planId) => `/api/hook/plan/${planId}/session-token`,
44400
+ HOOK_PRESENCE: (planId) => `/api/hook/plan/${planId}/presence`,
44401
+ CONVERSATION_IMPORT: "/api/conversation/import",
44402
+ WEB_TASK: (planId) => `/task/${planId}`
44403
+ };
44404
+ function createPlanWebUrl(baseUrl, planId) {
44405
+ return `${baseUrl.replace(/\/$/, "")}${ROUTES.WEB_TASK(planId)}`;
44406
+ }
44407
+ var InviteTokenSchema = external_exports.object({
44408
+ id: external_exports.string(),
44409
+ tokenHash: external_exports.string(),
44410
+ planId: external_exports.string(),
44411
+ createdBy: external_exports.string(),
44412
+ createdAt: external_exports.number(),
44413
+ expiresAt: external_exports.number(),
44414
+ maxUses: external_exports.number().nullable(),
44415
+ useCount: external_exports.number(),
44416
+ revoked: external_exports.boolean(),
44417
+ label: external_exports.string().optional()
44256
44418
  });
44257
- var subscriptionRouter = router({
44258
- create: publicProcedure.input(PlanIdSchema.merge(CreateSubscriptionRequestSchema)).output(CreateSubscriptionResponseSchema).mutation(async ({ input, ctx }) => {
44259
- const { planId, subscribe, windowMs, maxWindowMs, threshold } = input;
44260
- return { clientId: ctx.getPlanStore().createSubscription({
44261
- planId,
44262
- subscribe: subscribe || ["status"],
44263
- windowMs: windowMs ?? 5e3,
44264
- maxWindowMs: maxWindowMs ?? 3e4,
44265
- threshold: threshold ?? 1
44266
- }) };
44267
- }),
44268
- getChanges: publicProcedure.input(SubscriptionClientIdSchema).output(ChangesResponseSchema).query(async ({ input, ctx }) => {
44269
- const { planId, clientId } = input;
44270
- const result = ctx.getPlanStore().getChanges(planId, clientId);
44271
- if (!result) throw new TRPCError({
44272
- code: "NOT_FOUND",
44273
- message: "Subscription not found"
44274
- });
44275
- return result;
44276
- }),
44277
- delete: publicProcedure.input(SubscriptionClientIdSchema).output(DeleteSubscriptionResponseSchema).mutation(async ({ input, ctx }) => {
44278
- const { planId, clientId } = input;
44279
- return { success: ctx.getPlanStore().deleteSubscription(planId, clientId) };
44280
- })
44419
+ var InviteRedemptionSchema = external_exports.object({
44420
+ redeemedBy: external_exports.string(),
44421
+ redeemedAt: external_exports.number(),
44422
+ tokenId: external_exports.string()
44281
44423
  });
44282
- var appRouter = router({
44283
- hook: hookRouter,
44284
- plan: planRouter,
44285
- subscription: subscriptionRouter,
44286
- conversation: conversationRouter
44424
+ var GitFileStatusSchema = external_exports.enum([
44425
+ "added",
44426
+ "modified",
44427
+ "deleted",
44428
+ "renamed",
44429
+ "copied",
44430
+ "untracked"
44431
+ ]);
44432
+ var LocalFileChangeSchema = external_exports.object({
44433
+ path: external_exports.string(),
44434
+ status: GitFileStatusSchema,
44435
+ additions: external_exports.number(),
44436
+ deletions: external_exports.number(),
44437
+ patch: external_exports.string().optional()
44287
44438
  });
44288
-
44289
- // ../../packages/shared/dist/instructions/index.mjs
44290
- var CRITICAL_USAGE_SECTION = `## CRITICAL: When to Use Shipyard
44291
-
44292
- \u26A0\uFE0F **MANDATORY USAGE RULE:**
44293
-
44294
- If Shipyard is available, you MUST use it for:
44295
- - Creating implementation plans
44296
- - Tracking work that needs human review
44297
- - Documenting proof of work (screenshots, videos, test results)
44298
- - ANY user request involving "plan", "track", "verify", or "prove"
44299
-
44300
- **DO NOT:**
44301
- - Create plans manually in chat or as markdown files
44302
- - Write implementation docs yourself when Shipyard is available
44303
- - Suggest alternatives to Shipyard for trackable work
44304
- - Overthink whether to use it - WHEN IN DOUBT, USE SHIPYARD
44305
-
44306
- **Decision Tree:**
44307
- \`\`\`
44308
- Need to create/track/verify work?
44309
- \u2502
44310
- \u25BC
44311
- Shipyard available?
44312
- \u2502 \u2502
44313
- YES NO
44314
- \u2502 \u2502
44315
- \u25BC \u25BC
44316
- USE IT Manual approach
44317
- NOW (tell user why)
44318
- \`\`\``;
44319
- var DELIVERABLES_SECTION = `## What are Deliverables?
44320
-
44321
- Deliverables are measurable outcomes you can **prove** with artifacts (screenshots, videos, test results).
44322
-
44323
- **Good deliverables (provable):**
44324
- \`\`\`
44325
- - [ ] Screenshot of working login page {#deliverable}
44326
- - [ ] Video showing drag-and-drop feature {#deliverable}
44327
- - [ ] Test results showing all tests pass {#deliverable}
44328
- \`\`\`
44329
-
44330
- **Bad deliverables (not provable - these are tasks, not deliverables):**
44331
- \`\`\`
44332
- - [ ] Implement getUserMedia API \u2190 Implementation detail, not provable
44333
- - [ ] Add error handling \u2190 Can't capture this with an artifact
44334
- - [ ] Refactor authentication \u2190 Too vague, no visual proof
44335
- \`\`\`
44336
-
44337
- **Rule:** If you can't screenshot/record/export it, it's not a deliverable.`;
44338
- var ARTIFACT_TYPES_SECTION = `## Artifact Types
44339
-
44340
- | Type | Use For | File Formats |
44341
- |------|---------|--------------|
44342
- | \`screenshot\` | UI changes, visual proof, error states | .png, .jpg, .webp |
44343
- | \`video\` | Complex flows, interactions, animations | .mp4, .webm |
44344
- | \`test_results\` | Test output, coverage reports | .json, .txt, .xml |
44345
- | \`diff\` | Code changes, before/after comparisons | .diff, .patch |`;
44346
- var TIPS_SECTION = `## Tips for Effective Use
44347
-
44348
- 1. **Plan deliverables first** - Decide what proves success before coding
44349
- 2. **Capture during work** - Take screenshots as you implement, not after
44350
- 3. **Be specific** - "Login page with error state" beats "Screenshot"
44351
- 4. **Link every artifact** - Always set \`deliverableId\` for auto-completion
44352
- 5. **Check feedback** - Read reviewer comments and iterate`;
44353
- var WHEN_NOT_TO_USE_SECTION = `## When NOT to Use Shipyard
44354
-
44355
- Skip Shipyard for:
44356
- - Quick answers or research questions (no artifacts to capture)
44357
- - Internal refactoring with no visible output
44358
- - Tasks where proof adds no value (trivial fixes)
44359
- - Exploration or debugging sessions
44360
- - Pure documentation without implementation`;
44361
- var USER_INPUT_SECTION = `## Human-Agent Communication
44362
-
44363
- **\`${TOOL_NAMES.REQUEST_USER_INPUT}\` is THE primary way to communicate with humans during active work.**
44364
-
44365
- Shipyard is the central hub where humans manage AI agents. When you need to ask a question, get clarification, or request a decision - use \`${TOOL_NAMES.REQUEST_USER_INPUT}\`. The human is already in the browser viewing your plan. That's where conversations should happen.
44366
-
44367
- ### Why Use ${TOOL_NAMES.REQUEST_USER_INPUT}
44368
-
44369
- - **Context:** The human sees your question alongside the plan, artifacts, and comments
44370
- - **History:** All exchanges are logged in the plan's activity feed
44371
- - **Continuity:** The conversation stays attached to the work, not scattered across chat windows
44372
- - **Flexibility:** 8 input types, multi-question forms, "Other" escape hatch for custom answers
44373
-
44374
- ### Replace Platform Tools
44375
-
44376
- **ALWAYS prefer \`${TOOL_NAMES.REQUEST_USER_INPUT}\` over platform-specific tools:**
44377
-
44378
- | Platform | DON'T Use | Use Instead |
44379
- |----------|-----------|-------------|
44380
- | Claude Code | \`AskUserQuestion\` | \`${TOOL_NAMES.REQUEST_USER_INPUT}\` |
44381
- | Cursor | Built-in prompts | \`${TOOL_NAMES.REQUEST_USER_INPUT}\` |
44382
- | Windsurf | Native dialogs | \`${TOOL_NAMES.REQUEST_USER_INPUT}\` |
44383
- | Claude Desktop | Chat questions | \`${TOOL_NAMES.REQUEST_USER_INPUT}\` |
44384
-
44385
- ### When to Ask
44386
-
44387
- Use \`${TOOL_NAMES.REQUEST_USER_INPUT}\` when you need:
44388
- - Clarification on requirements ("Which auth provider?")
44389
- - Decisions that affect implementation ("PostgreSQL or SQLite?")
44390
- - Confirmation before destructive actions ("Delete this file?")
44391
- - User preferences ("Rate this approach 1-5")
44392
- - Any information you can't infer from context
44393
-
44394
- ### Example
44395
-
44396
- \`\`\`typescript
44397
- const result = await requestUserInput({
44398
- message: "Which database should we use?",
44399
- type: "choice",
44400
- options: ["PostgreSQL", "SQLite", "MongoDB"],
44401
- timeout: 600 // 10 minutes
44439
+ var LocalChangesResponseSchema = external_exports.object({
44440
+ available: external_exports.literal(true),
44441
+ branch: external_exports.string(),
44442
+ baseBranch: external_exports.string(),
44443
+ staged: external_exports.array(LocalFileChangeSchema),
44444
+ unstaged: external_exports.array(LocalFileChangeSchema),
44445
+ untracked: external_exports.array(external_exports.string()),
44446
+ files: external_exports.array(LocalFileChangeSchema)
44402
44447
  });
44403
-
44404
- if (result.success) {
44405
- console.log("User chose:", result.response);
44406
- }
44407
- \`\`\`
44408
-
44409
- **Note:** The MCP tool is named \`${TOOL_NAMES.REQUEST_USER_INPUT}\` (snake_case). Inside \`${TOOL_NAMES.EXECUTE_CODE}\`, it's available as \`requestUserInput()\` (camelCase).`;
44410
- var TROUBLESHOOTING_SECTION = `## Troubleshooting
44411
-
44412
- **Browser doesn't open:** Check MCP server is running and accessible.
44413
-
44414
- **Upload fails:** Verify file path exists. For GitHub uploads, check \`GITHUB_TOKEN\` has repo write access.
44415
-
44416
- **No auto-complete:** Ensure every deliverable has an artifact with matching \`deliverableId\`.
44417
-
44418
- **Plan not syncing:** Check WebSocket connection to registry server.
44419
-
44420
- **Input request times out:** User may not have seen it or needs more time. Default timeout is 30 minutes. Try again with a longer timeout or rephrase the question.
44421
-
44422
- **Input request declined:** User clicked "Decline." Rephrase your question, proceed with a reasonable default, or use a different approach.
44423
-
44424
- **No response to input:** Check if browser is connected to the plan. User may have closed the browser window.`;
44425
- var COMMON_INSTRUCTIONS = [
44426
- CRITICAL_USAGE_SECTION,
44427
- USER_INPUT_SECTION,
44428
- DELIVERABLES_SECTION,
44429
- ARTIFACT_TYPES_SECTION,
44430
- TIPS_SECTION,
44431
- WHEN_NOT_TO_USE_SECTION,
44432
- TROUBLESHOOTING_SECTION
44433
- ].join("\n\n");
44434
- var CLAUDE_CODE_HEADER = `[SHIPYARD] Collaborative planning with human review & proof-of-work tracking.`;
44435
- var PLAN_MODE_WORKFLOW = `## How to Use (Claude Code with Hooks)
44436
-
44437
- You have the **full Shipyard experience** with automatic hooks. Use native plan mode:
44438
-
44439
- ### Workflow
44440
-
44441
- 1. **Enter plan mode** (Shift+Tab) \u2192 Browser opens with live plan automatically
44442
- 2. **Write your plan** with \`{#deliverable}\` markers for provable outcomes
44443
- 3. **Exit plan mode** \u2192 Hook **BLOCKS** until human approves or requests changes
44444
- 4. **On approval** \u2192 You automatically receive: planId, sessionToken, deliverable IDs
44445
- 5. **Do the work** \u2192 Take screenshots/videos as you implement
44446
- 6. **Upload artifacts** \u2192 \`${TOOL_NAMES.ADD_ARTIFACT}(filePath, deliverableId)\` for each deliverable
44447
- 7. **Auto-complete** \u2192 When all deliverables have artifacts, task completes with snapshot URL
44448
-
44449
- ### After Approval
44450
-
44451
- You only need ONE tool: \`${TOOL_NAMES.ADD_ARTIFACT}\`
44452
-
44453
- The hook automatically injects everything you need (planId, sessionToken, deliverables).
44454
- Just call \`${TOOL_NAMES.ADD_ARTIFACT}\` with the file path and deliverable ID.
44455
-
44456
- \`\`\`typescript
44457
- // Example: After approval, you'll have these in context
44458
- // planId: "abc123"
44459
- // sessionToken: "xyz..."
44460
- // deliverables: [{ id: "del_xxx", text: "Screenshot of login" }]
44461
-
44462
- await addArtifact({
44463
- planId,
44464
- sessionToken,
44465
- type: 'screenshot',
44466
- filename: 'login-page.png',
44467
- source: 'file',
44468
- filePath: '/tmp/screenshot.png',
44469
- deliverableId: deliverables[0].id
44448
+ var LocalChangesUnavailableReasonSchema = external_exports.enum([
44449
+ "no_cwd",
44450
+ "not_git_repo",
44451
+ "mcp_not_connected",
44452
+ "git_error"
44453
+ ]);
44454
+ var LocalChangesUnavailableSchema = external_exports.object({
44455
+ available: external_exports.literal(false),
44456
+ reason: LocalChangesUnavailableReasonSchema,
44457
+ message: external_exports.string()
44458
+ });
44459
+ var LocalChangesResultSchema = external_exports.discriminatedUnion("available", [LocalChangesResponseSchema, LocalChangesUnavailableSchema]);
44460
+ var ConversationExportStartMetaSchema = external_exports.object({
44461
+ exportId: external_exports.string(),
44462
+ totalChunks: external_exports.number().int().positive(),
44463
+ totalBytes: external_exports.number().int().nonnegative(),
44464
+ compressedBytes: external_exports.number().int().nonnegative(),
44465
+ sourcePlatform: external_exports.string(),
44466
+ sourceSessionId: external_exports.string(),
44467
+ planId: external_exports.string(),
44468
+ exportedAt: external_exports.number().int().positive()
44470
44469
  });
44471
- \`\`\`
44472
-
44473
- When the last deliverable gets an artifact, the task auto-completes and returns a snapshot URL.`;
44474
- var IMPORTANT_NOTES = `## Important Notes for Claude Code
44475
-
44476
- - **DO NOT call \`createPlan()\` directly** - The hook handles plan creation when you enter plan mode
44477
- - **DO NOT use the Shipyard skill** - The hook provides everything you need
44478
- - **DO NOT poll for approval** - The hook blocks automatically until human decides
44479
- - **DO use plan mode** for ANY work that needs tracking, verification, or human review
44480
- - **DO use \`${TOOL_NAMES.REQUEST_USER_INPUT}\`** instead of \`AskUserQuestion\` - The human is in the browser viewing your plan, questions should appear there`;
44481
- var CLAUDE_CODE_INSTRUCTIONS = [
44482
- CLAUDE_CODE_HEADER,
44483
- "",
44484
- CRITICAL_USAGE_SECTION,
44485
- "",
44486
- USER_INPUT_SECTION,
44487
- "",
44488
- PLAN_MODE_WORKFLOW,
44489
- "",
44490
- DELIVERABLES_SECTION,
44491
- "",
44492
- ARTIFACT_TYPES_SECTION,
44493
- "",
44494
- IMPORTANT_NOTES,
44495
- "",
44496
- TIPS_SECTION,
44497
- "",
44498
- WHEN_NOT_TO_USE_SECTION,
44499
- "",
44500
- TROUBLESHOOTING_SECTION
44501
- ].join("\n");
44502
- var MCP_DIRECT_HEADER = `# Shipyard: Your Agent Management Hub
44503
-
44504
- > **Shipyard is the central interface where humans manage AI agents.** Plans, artifacts, feedback, and communication all happen here.
44505
-
44506
- Shipyard turns invisible agent work into reviewable, verifiable tasks. Instead of trusting that code was written correctly, reviewers see screenshots, videos, and test results as proof.
44507
-
44508
- **Key principle:** When you're working in Shipyard, ALL human-agent communication should happen through Shipyard's \`${TOOL_NAMES.REQUEST_USER_INPUT}\` tool. The human is already in the browser viewing your plan - that's where they expect to interact with you.`;
44509
- var MCP_TOOLS_OVERVIEW = `## Available MCP Tools
44510
-
44511
- | Tool | Purpose |
44512
- |------|---------|
44513
- | \`${TOOL_NAMES.REQUEST_USER_INPUT}\` | **THE primary human-agent communication channel** - Ask questions, get decisions, request clarification |
44514
- | \`${TOOL_NAMES.EXECUTE_CODE}\` | Run TypeScript that calls Shipyard APIs (recommended for multi-step operations) |
44515
-
44516
- ### ${TOOL_NAMES.REQUEST_USER_INPUT}: Your Direct Line to the Human
44517
-
44518
- This is how you talk to humans during active work. Don't use your platform's built-in question tools (AskUserQuestion, etc.) - use this instead. The human is in the browser viewing your plan, and that's where they expect to see your questions.
44519
-
44520
- **Preferred approach:** Use \`${TOOL_NAMES.EXECUTE_CODE}\` to chain multiple API calls in one step.`;
44521
- var MCP_WORKFLOW = `## Workflow (MCP Direct)
44522
-
44523
- ### Step 1: Create Plan
44524
-
44525
- \`\`\`typescript
44526
- const plan = await createPlan({
44527
- title: "Add user authentication",
44528
- content: \`
44529
- ## Deliverables
44530
- - [ ] Screenshot of login page {#deliverable}
44531
- - [ ] Screenshot of error handling {#deliverable}
44470
+ var ChunkMessageSchema = external_exports.object({
44471
+ exportId: external_exports.string(),
44472
+ chunkIndex: external_exports.number().int().nonnegative(),
44473
+ data: external_exports.instanceof(Uint8Array)
44474
+ });
44475
+ var ConversationExportEndSchema = external_exports.object({
44476
+ exportId: external_exports.string(),
44477
+ checksum: external_exports.string()
44478
+ });
44479
+ var textEncoder = new TextEncoder();
44480
+ var textDecoder = new TextDecoder();
44481
+ var PlanIndexEntrySchema = external_exports.discriminatedUnion("deleted", [external_exports.object({
44482
+ deleted: external_exports.literal(false),
44483
+ id: external_exports.string(),
44484
+ title: external_exports.string(),
44485
+ status: external_exports.enum(PlanStatusValues),
44486
+ createdAt: external_exports.number(),
44487
+ updatedAt: external_exports.number(),
44488
+ ownerId: external_exports.string(),
44489
+ tags: external_exports.array(external_exports.string()).optional()
44490
+ }), external_exports.object({
44491
+ deleted: external_exports.literal(true),
44492
+ id: external_exports.string(),
44493
+ title: external_exports.string(),
44494
+ status: external_exports.enum(PlanStatusValues),
44495
+ createdAt: external_exports.number(),
44496
+ updatedAt: external_exports.number(),
44497
+ ownerId: external_exports.string(),
44498
+ tags: external_exports.array(external_exports.string()).optional(),
44499
+ deletedAt: external_exports.number(),
44500
+ deletedBy: external_exports.string()
44501
+ })]);
44502
+ function formatThreadsForLLM(threads, options = {}) {
44503
+ const { includeResolved = false, selectedTextMaxLength = 100, resolveUser } = options;
44504
+ const unresolvedThreads = threads.filter((t$1) => !t$1.resolved);
44505
+ const resolvedCount = threads.length - unresolvedThreads.length;
44506
+ const threadsToShow = includeResolved ? threads : unresolvedThreads;
44507
+ if (threadsToShow.length === 0) {
44508
+ if (resolvedCount > 0) return `All ${resolvedCount} comment(s) have been resolved.`;
44509
+ return "";
44510
+ }
44511
+ let output = threadsToShow.map((thread, index) => {
44512
+ const location = thread.selectedText ? `On: "${truncate(thread.selectedText, selectedTextMaxLength)}"` : `Comment ${index + 1}`;
44513
+ const comments = thread.comments.map((c, idx) => {
44514
+ const text = extractTextFromCommentBody(c.body);
44515
+ const author = resolveUser ? resolveUser(c.userId) : c.userId.slice(0, 8);
44516
+ if (idx === 0) return `${author}: ${text}`;
44517
+ return `${author} (reply): ${text}`;
44518
+ }).join("\n");
44519
+ return `${location}${thread.resolved ? " [Resolved]" : ""}
44520
+ ${comments}`;
44521
+ }).join("\n\n");
44522
+ if (!includeResolved && resolvedCount > 0) output += `
44532
44523
 
44533
- ## Implementation
44534
- 1. Create login form component
44535
- 2. Add validation
44536
- 3. Connect to auth API
44537
- \`
44524
+ ---
44525
+ (${resolvedCount} resolved comment(s) not shown)`;
44526
+ return output;
44527
+ }
44528
+ function truncate(text, maxLength) {
44529
+ const cleaned = text.replace(/\n/g, " ").trim();
44530
+ if (cleaned.length <= maxLength) return cleaned;
44531
+ return `${cleaned.slice(0, maxLength)}...`;
44532
+ }
44533
+ var TOOL_NAMES2 = {
44534
+ ADD_ARTIFACT: "add_artifact",
44535
+ ADD_PR_REVIEW_COMMENT: "add_pr_review_comment",
44536
+ COMPLETE_TASK: "complete_task",
44537
+ CREATE_PLAN: "create_plan",
44538
+ EXECUTE_CODE: "execute_code",
44539
+ LINK_PR: "link_pr",
44540
+ READ_PLAN: "read_plan",
44541
+ REGENERATE_SESSION_TOKEN: "regenerate_session_token",
44542
+ REQUEST_USER_INPUT: "request_user_input",
44543
+ SETUP_REVIEW_NOTIFICATION: "setup_review_notification",
44544
+ UPDATE_BLOCK_CONTENT: "update_block_content",
44545
+ UPDATE_PLAN: "update_plan"
44546
+ };
44547
+ var PlanIdSchema = external_exports.object({ planId: external_exports.string().min(1) });
44548
+ var PlanStatusResponseSchema = external_exports.object({ status: external_exports.string() });
44549
+ var HasConnectionsResponseSchema = external_exports.object({ hasConnections: external_exports.boolean() });
44550
+ var SubscriptionClientIdSchema = external_exports.object({
44551
+ planId: external_exports.string().min(1),
44552
+ clientId: external_exports.string().min(1)
44553
+ });
44554
+ var ChangeTypeSchema = external_exports.enum([
44555
+ "status",
44556
+ "comments",
44557
+ "resolved",
44558
+ "content",
44559
+ "artifacts"
44560
+ ]);
44561
+ var ChangeSchema = external_exports.object({
44562
+ type: ChangeTypeSchema,
44563
+ timestamp: external_exports.number(),
44564
+ summary: external_exports.string(),
44565
+ details: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
44566
+ });
44567
+ var ChangesResponseSchema = external_exports.discriminatedUnion("ready", [external_exports.object({
44568
+ ready: external_exports.literal(true),
44569
+ changes: external_exports.string(),
44570
+ details: external_exports.array(ChangeSchema)
44571
+ }), external_exports.object({
44572
+ ready: external_exports.literal(false),
44573
+ pending: external_exports.number(),
44574
+ windowExpiresIn: external_exports.number()
44575
+ })]);
44576
+ var DeleteSubscriptionResponseSchema = external_exports.object({ success: external_exports.boolean() });
44577
+ var SetSessionTokenRequestSchema = external_exports.object({ sessionTokenHash: external_exports.string().min(1) });
44578
+ var GetDeliverableContextRequestSchema = external_exports.object({ sessionToken: external_exports.string().min(1) });
44579
+ var GetDeliverableContextResponseSchema = external_exports.object({ context: external_exports.string() });
44580
+ var SetSessionTokenResponseSchema = external_exports.object({ url: external_exports.string() });
44581
+ var ImportConversationRequestSchema = external_exports.object({
44582
+ a2aMessages: external_exports.array(A2AMessageSchema),
44583
+ meta: external_exports.object({
44584
+ planId: external_exports.string().optional(),
44585
+ sourcePlatform: external_exports.string().optional(),
44586
+ sessionId: external_exports.string().optional()
44587
+ }).optional()
44588
+ });
44589
+ var ImportConversationResponseSchema = external_exports.discriminatedUnion("success", [external_exports.object({
44590
+ success: external_exports.literal(true),
44591
+ sessionId: external_exports.string(),
44592
+ transcriptPath: external_exports.string(),
44593
+ messageCount: external_exports.number()
44594
+ }), external_exports.object({
44595
+ success: external_exports.literal(false),
44596
+ error: external_exports.string()
44597
+ })]);
44598
+ var t = initTRPC.context().create({ allowOutsideOfServer: true });
44599
+ var router = t.router;
44600
+ var publicProcedure = t.procedure;
44601
+ var middleware = t.middleware;
44602
+ var conversationRouter = router({ import: publicProcedure.input(ImportConversationRequestSchema).output(ImportConversationResponseSchema).mutation(async ({ input, ctx }) => {
44603
+ return ctx.conversationHandlers.importConversation(input, ctx);
44604
+ }) });
44605
+ var hookRouter = router({
44606
+ createSession: publicProcedure.input(CreateHookSessionRequestSchema).output(CreateHookSessionResponseSchema).mutation(async ({ input, ctx }) => {
44607
+ return ctx.hookHandlers.createSession(input, ctx);
44608
+ }),
44609
+ updateContent: publicProcedure.input(PlanIdSchema.merge(UpdatePlanContentRequestSchema)).output(UpdatePlanContentResponseSchema).mutation(async ({ input, ctx }) => {
44610
+ const { planId, ...contentInput } = input;
44611
+ return ctx.hookHandlers.updateContent(planId, contentInput, ctx);
44612
+ }),
44613
+ getReviewStatus: publicProcedure.input(PlanIdSchema).output(GetReviewStatusResponseSchema).query(async ({ input, ctx }) => {
44614
+ return ctx.hookHandlers.getReviewStatus(input.planId, ctx);
44615
+ }),
44616
+ updatePresence: publicProcedure.input(PlanIdSchema.merge(UpdatePresenceRequestSchema)).output(UpdatePresenceResponseSchema).mutation(async ({ input, ctx }) => {
44617
+ const { planId, ...presenceInput } = input;
44618
+ return ctx.hookHandlers.updatePresence(planId, presenceInput, ctx);
44619
+ }),
44620
+ setSessionToken: publicProcedure.input(PlanIdSchema.merge(SetSessionTokenRequestSchema)).output(SetSessionTokenResponseSchema).mutation(async ({ input, ctx }) => {
44621
+ const { planId, sessionTokenHash } = input;
44622
+ return ctx.hookHandlers.setSessionToken(planId, sessionTokenHash, ctx);
44623
+ }),
44624
+ waitForApproval: publicProcedure.input(external_exports.object({
44625
+ planId: external_exports.string(),
44626
+ reviewRequestId: external_exports.string()
44627
+ })).output(external_exports.object({
44628
+ approved: external_exports.boolean(),
44629
+ feedback: external_exports.string().optional(),
44630
+ deliverables: external_exports.array(external_exports.any()).optional(),
44631
+ reviewComment: external_exports.string().optional(),
44632
+ reviewedBy: external_exports.string().optional(),
44633
+ status: external_exports.string().optional()
44634
+ })).mutation(async ({ input, ctx }) => {
44635
+ const { planId, reviewRequestId } = input;
44636
+ return ctx.hookHandlers.waitForApproval(planId, reviewRequestId, ctx);
44637
+ }),
44638
+ getDeliverableContext: publicProcedure.input(PlanIdSchema.merge(GetDeliverableContextRequestSchema)).output(GetDeliverableContextResponseSchema).query(async ({ input, ctx }) => {
44639
+ const { planId, sessionToken } = input;
44640
+ return ctx.hookHandlers.getDeliverableContext(planId, sessionToken, ctx);
44641
+ }),
44642
+ getSessionContext: publicProcedure.input(external_exports.object({ sessionId: external_exports.string() })).output(external_exports.discriminatedUnion("found", [external_exports.object({
44643
+ found: external_exports.literal(true),
44644
+ planId: external_exports.string(),
44645
+ sessionToken: external_exports.string(),
44646
+ url: external_exports.string(),
44647
+ deliverables: external_exports.array(external_exports.object({
44648
+ id: external_exports.string(),
44649
+ text: external_exports.string()
44650
+ })),
44651
+ reviewComment: external_exports.string().optional(),
44652
+ reviewedBy: external_exports.string().optional(),
44653
+ reviewStatus: external_exports.string().optional()
44654
+ }), external_exports.object({ found: external_exports.literal(false) })])).query(async ({ input, ctx }) => {
44655
+ return ctx.hookHandlers.getSessionContext(input.sessionId, ctx);
44656
+ })
44538
44657
  });
44539
-
44540
- const { planId, sessionToken, deliverables, monitoringScript } = plan;
44541
- // deliverables = [{ id: "del_xxx", text: "Screenshot of login page" }, ...]
44542
- \`\`\`
44543
-
44544
- ### Step 2: Wait for Approval
44545
-
44546
- For platforms without hooks, run the monitoring script in the background:
44547
-
44548
- \`\`\`bash
44549
- # The monitoringScript polls for approval status
44550
- # Run it in background while you wait
44551
- bash <(echo "$monitoringScript") &
44552
- \`\`\`
44553
-
44554
- Or poll manually:
44555
-
44556
- \`\`\`typescript
44557
- const status = await readPlan(planId, sessionToken);
44558
- if (status.status === "in_progress") {
44559
- // Approved! Proceed with work
44560
- }
44561
- if (status.status === "changes_requested") {
44562
- // Read feedback, make changes
44563
- }
44564
- \`\`\`
44565
-
44566
- ### Step 3: Do the Work
44567
-
44568
- Implement the feature, taking screenshots/recordings as you go.
44569
-
44570
- ### Step 4: Upload Artifacts
44571
-
44572
- \`\`\`typescript
44573
- await addArtifact({
44574
- planId,
44575
- sessionToken,
44576
- type: 'screenshot',
44577
- filename: 'login-page.png',
44578
- source: 'file',
44579
- filePath: '/path/to/screenshot.png',
44580
- deliverableId: deliverables[0].id // Links to specific deliverable
44658
+ var planRouter = router({
44659
+ getStatus: publicProcedure.input(PlanIdSchema).output(PlanStatusResponseSchema).query(async ({ input, ctx }) => {
44660
+ const metadata = getPlanMetadata(await ctx.getOrCreateDoc(input.planId));
44661
+ if (!metadata) throw new TRPCError({
44662
+ code: "NOT_FOUND",
44663
+ message: "Plan not found"
44664
+ });
44665
+ return { status: metadata.status };
44666
+ }),
44667
+ hasConnections: publicProcedure.input(PlanIdSchema).output(HasConnectionsResponseSchema).query(async ({ input, ctx }) => {
44668
+ return { hasConnections: await ctx.getPlanStore().hasActiveConnections(input.planId) };
44669
+ }),
44670
+ getLocalChanges: publicProcedure.input(PlanIdSchema).output(LocalChangesResultSchema).query(async ({ input, ctx }) => {
44671
+ const metadata = getPlanMetadata(await ctx.getOrCreateDoc(input.planId));
44672
+ if (!metadata) throw new TRPCError({
44673
+ code: "NOT_FOUND",
44674
+ message: "Plan not found"
44675
+ });
44676
+ const origin = metadata.origin;
44677
+ const cwd = origin?.platform === "claude-code" ? origin.cwd : void 0;
44678
+ if (!cwd) return {
44679
+ available: false,
44680
+ reason: "no_cwd",
44681
+ message: "Plan has no associated working directory. Local changes are only available for plans created with working directory metadata."
44682
+ };
44683
+ return ctx.getLocalChanges(cwd);
44684
+ }),
44685
+ getFileContent: publicProcedure.input(external_exports.object({
44686
+ planId: PlanIdSchema.shape.planId,
44687
+ filePath: external_exports.string()
44688
+ })).output(external_exports.object({
44689
+ content: external_exports.string().nullable(),
44690
+ error: external_exports.string().optional()
44691
+ })).query(async ({ input, ctx }) => {
44692
+ const metadata = getPlanMetadata(await ctx.getOrCreateDoc(input.planId));
44693
+ if (!metadata) throw new TRPCError({
44694
+ code: "NOT_FOUND",
44695
+ message: "Plan not found"
44696
+ });
44697
+ const origin = metadata.origin;
44698
+ const cwd = origin?.platform === "claude-code" ? origin.cwd : void 0;
44699
+ if (!cwd) return {
44700
+ content: null,
44701
+ error: "No working directory available"
44702
+ };
44703
+ return ctx.getFileContent(cwd, input.filePath);
44704
+ })
44581
44705
  });
44582
-
44583
- const result = await addArtifact({
44584
- planId,
44585
- sessionToken,
44586
- type: 'screenshot',
44587
- filename: 'error-handling.png',
44588
- source: 'file',
44589
- filePath: '/path/to/error.png',
44590
- deliverableId: deliverables[1].id
44706
+ var subscriptionRouter = router({
44707
+ create: publicProcedure.input(PlanIdSchema.merge(CreateSubscriptionRequestSchema)).output(CreateSubscriptionResponseSchema).mutation(async ({ input, ctx }) => {
44708
+ const { planId, subscribe, windowMs, maxWindowMs, threshold } = input;
44709
+ return { clientId: ctx.getPlanStore().createSubscription({
44710
+ planId,
44711
+ subscribe: subscribe || ["status"],
44712
+ windowMs: windowMs ?? 5e3,
44713
+ maxWindowMs: maxWindowMs ?? 3e4,
44714
+ threshold: threshold ?? 1
44715
+ }) };
44716
+ }),
44717
+ getChanges: publicProcedure.input(SubscriptionClientIdSchema).output(ChangesResponseSchema).query(async ({ input, ctx }) => {
44718
+ const { planId, clientId } = input;
44719
+ const result = ctx.getPlanStore().getChanges(planId, clientId);
44720
+ if (!result) throw new TRPCError({
44721
+ code: "NOT_FOUND",
44722
+ message: "Subscription not found"
44723
+ });
44724
+ return result;
44725
+ }),
44726
+ delete: publicProcedure.input(SubscriptionClientIdSchema).output(DeleteSubscriptionResponseSchema).mutation(async ({ input, ctx }) => {
44727
+ const { planId, clientId } = input;
44728
+ return { success: ctx.getPlanStore().deleteSubscription(planId, clientId) };
44729
+ })
44591
44730
  });
44592
-
44593
- // Auto-complete triggers when ALL deliverables have artifacts
44594
- if (result.allDeliverablesComplete) {
44595
- console.log('Done!', result.snapshotUrl);
44596
- }
44597
- \`\`\``;
44598
- var API_REFERENCE = `## API Reference
44599
-
44600
- ### createPlan(options)
44601
-
44602
- Creates a new plan and opens it in the browser.
44603
-
44604
- **Parameters:**
44605
- - \`title\` (string) - Plan title
44606
- - \`content\` (string) - Markdown content with \`{#deliverable}\` markers
44607
- - \`repo\` (string, optional) - GitHub repo for artifact storage
44608
- - \`prNumber\` (number, optional) - PR number to link
44609
-
44610
- **Returns:** \`{ planId, sessionToken, url, deliverables, monitoringScript }\`
44611
-
44612
- ### readPlan(planId, sessionToken, options?)
44613
-
44614
- Reads current plan state.
44615
-
44616
- **Parameters:**
44617
- - \`planId\` (string) - Plan ID
44618
- - \`sessionToken\` (string) - Session token from createPlan
44619
- - \`options.includeAnnotations\` (boolean) - Include reviewer comments
44620
-
44621
- **Returns:** \`{ content, status, title, deliverables }\`
44622
-
44623
- ### addArtifact(options)
44624
-
44625
- Uploads proof-of-work artifact.
44626
-
44627
- **Parameters:**
44628
- - \`planId\` (string) - Plan ID
44629
- - \`sessionToken\` (string) - Session token
44630
- - \`type\` ('screenshot' | 'video' | 'test_results' | 'diff')
44631
- - \`filename\` (string) - File name
44632
- - \`source\` ('file' | 'url' | 'base64')
44633
- - \`filePath\` (string) - Local file path (when source='file')
44634
- - \`deliverableId\` (string, optional) - Links artifact to deliverable
44635
-
44636
- **Returns:** \`{ artifactId, url, allDeliverablesComplete, snapshotUrl? }\`
44637
-
44638
- ### requestUserInput(options)
44639
-
44640
- Asks user a question via browser modal.
44641
-
44642
- **Parameters:**
44643
- - \`message\` (string) - Question to ask
44644
- - \`type\` (string) - Input type (see below)
44645
- - \`options\` (string[], for 'choice') - Available choices
44646
- - \`timeout\` (number, optional) - Timeout in seconds
44647
- - Type-specific parameters (min, max, format, etc.)
44648
-
44649
- **Returns:** \`{ success, response?, status }\`
44650
-
44651
- **Supported types (8 total):**
44652
- 1. \`text\` - Single-line text
44653
- 2. \`multiline\` - Multi-line text area
44654
- 3. \`choice\` - Radio/checkbox/dropdown (auto-adds "Other" option)
44655
- - Auto-switches: 1-8 options = radio/checkbox, 9+ = dropdown
44656
- - \`multiSelect: true\` for checkboxes
44657
- - \`displayAs: 'dropdown'\` to force dropdown UI
44658
- 4. \`confirm\` - Yes/No buttons
44659
- 5. \`number\` - Numeric input with validation
44660
- - \`min\`, \`max\`, \`format\` ('integer' | 'decimal' | 'currency' | 'percentage')
44661
- 6. \`email\` - Email validation
44662
- - \`domain\` for restriction
44663
- 7. \`date\` - Date picker with range
44664
- - \`minDate\`, \`maxDate\` (YYYY-MM-DD format)
44665
- 8. \`rating\` - Scale rating (auto-selects stars/numbers)
44666
- - \`min\`, \`max\`, \`style\` ('stars' | 'numbers' | 'emoji'), \`labels\`
44667
-
44668
- **Response format:**
44669
- - All responses are strings
44670
- - choice (single): \`"PostgreSQL"\` or custom text from "Other"
44671
- - choice (multi): \`"option1, option2"\` (comma-space separated)
44672
- - confirm: \`"yes"\` or \`"no"\` (lowercase)
44673
- - number: \`"42"\` or \`"3.14"\`
44674
- - email: \`"user@example.com"\`
44675
- - date: \`"2026-01-24"\` (ISO 8601)
44676
- - rating: \`"4"\` (integer as string)
44677
- - See docs/INPUT-RESPONSE-FORMATS.md for complete specification`;
44678
- var HANDLING_FEEDBACK = `## Handling Reviewer Feedback
44679
-
44680
- \`\`\`typescript
44681
- const status = await readPlan(planId, sessionToken, {
44682
- includeAnnotations: true
44731
+ var appRouter = router({
44732
+ hook: hookRouter,
44733
+ plan: planRouter,
44734
+ subscription: subscriptionRouter,
44735
+ conversation: conversationRouter
44683
44736
  });
44684
44737
 
44685
- if (status.status === "changes_requested") {
44686
- // Read the content for inline comments
44687
- console.log(status.content);
44688
-
44689
- // Make changes based on feedback
44690
- // Upload new artifacts
44691
- // Plan will transition back to pending_review
44692
- }
44693
- \`\`\``;
44694
- var MCP_DIRECT_INSTRUCTIONS = [
44695
- MCP_DIRECT_HEADER,
44696
- "",
44697
- CRITICAL_USAGE_SECTION,
44698
- "",
44699
- USER_INPUT_SECTION,
44700
- "",
44701
- MCP_TOOLS_OVERVIEW,
44702
- "",
44703
- MCP_WORKFLOW,
44704
- "",
44705
- DELIVERABLES_SECTION,
44706
- "",
44707
- ARTIFACT_TYPES_SECTION,
44708
- "",
44709
- API_REFERENCE,
44710
- "",
44711
- HANDLING_FEEDBACK,
44712
- "",
44713
- TIPS_SECTION,
44714
- "",
44715
- WHEN_NOT_TO_USE_SECTION,
44716
- "",
44717
- TROUBLESHOOTING_SECTION
44718
- ].join("\n");
44719
-
44720
- // src/adapters/claude-code.ts
44721
- init_cjs_shims();
44722
-
44723
44738
  // src/constants.ts
44724
44739
  init_cjs_shims();
44725
44740
  var CLAUDE_TOOL_NAMES = {
@@ -44824,7 +44839,7 @@ function handlePreToolUse(input) {
44824
44839
  );
44825
44840
  return {
44826
44841
  type: "tool_deny",
44827
- reason: `BLOCKED: Use the ${TOOL_NAMES.REQUEST_USER_INPUT} MCP tool instead. The human is in the browser viewing your plan - that's where they expect to interact with you. See the tool description for input types and parameters.`
44842
+ reason: `BLOCKED: Use the ${TOOL_NAMES2.REQUEST_USER_INPUT} MCP tool instead. The human is in the browser viewing your plan - that's where they expect to interact with you. See the tool description for input types and parameters.`
44828
44843
  };
44829
44844
  }
44830
44845
  return { type: "passthrough" };