opencodekit 0.21.4 → 0.21.6

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.
Files changed (32) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/template/.opencode/AGENTS.md +55 -36
  3. package/dist/template/.opencode/agent/build.md +13 -3
  4. package/dist/template/.opencode/agent/explore.md +14 -0
  5. package/dist/template/.opencode/agent/general.md +13 -2
  6. package/dist/template/.opencode/agent/painter.md +9 -0
  7. package/dist/template/.opencode/agent/plan.md +26 -4
  8. package/dist/template/.opencode/agent/review.md +10 -0
  9. package/dist/template/.opencode/agent/scout.md +16 -1
  10. package/dist/template/.opencode/agent/vision.md +23 -0
  11. package/dist/template/.opencode/command/design.md +27 -8
  12. package/dist/template/.opencode/command/plan.md +22 -0
  13. package/dist/template/.opencode/command/ship.md +31 -5
  14. package/dist/template/.opencode/command/status.md +14 -5
  15. package/dist/template/.opencode/command/ui-review.md +38 -18
  16. package/dist/template/.opencode/command/ui-slop-check.md +30 -7
  17. package/dist/template/.opencode/command/verify.md +3 -0
  18. package/dist/template/.opencode/memory.db +0 -0
  19. package/dist/template/.opencode/memory.db-shm +0 -0
  20. package/dist/template/.opencode/memory.db-wal +0 -0
  21. package/dist/template/.opencode/plugin/copilot-auth.ts +66 -41
  22. package/dist/template/.opencode/plugin/sdk/copilot/chat/convert-to-openai-compatible-chat-messages.ts +162 -168
  23. package/dist/template/.opencode/plugin/sdk/copilot/chat/map-openai-compatible-finish-reason.ts +16 -16
  24. package/dist/template/.opencode/plugin/sdk/copilot/chat/openai-compatible-chat-language-model.ts +807 -805
  25. package/dist/template/.opencode/plugin/sdk/copilot/chat/openai-compatible-prepare-tools.ts +77 -77
  26. package/dist/template/.opencode/plugin/sdk/copilot/copilot-provider.ts +75 -80
  27. package/dist/template/.opencode/skill/playwright/SKILL.md +51 -2
  28. package/dist/template/.opencode/skill/portless/SKILL.md +109 -0
  29. package/dist/template/.opencode/skill/terse-output-mode/SKILL.md +95 -0
  30. package/dist/template/.opencode/skill/think-in-code/SKILL.md +136 -0
  31. package/dist/template/.opencode/skill/ux-quality-gates/SKILL.md +137 -0
  32. package/package.json +1 -1
@@ -40,11 +40,12 @@ skill({ name: "beads" });
40
40
 
41
41
  ## Available Tools
42
42
 
43
- | Tool | Use When |
44
- | --------------- | --------------------- |
45
- | `br` | Task status and stats |
46
- | `git` | Git state and history |
47
- | `find_sessions` | Recent sessions |
43
+ | Tool | Use When |
44
+ | --------------- | ----------------------------------------------- |
45
+ | `br` | Task status and stats |
46
+ | `git` | Git state and history |
47
+ | `find_sessions` | Recent sessions |
48
+ | `portless` | Optional read-only local URL state if installed |
48
49
 
49
50
  ## Phase 1: Gather State (Parallel)
50
51
 
@@ -62,6 +63,14 @@ git branch --show-current
62
63
  git log --oneline -5
63
64
  ```
64
65
 
66
+ Optionally include Portless local URL state only if the binary is already installed:
67
+
68
+ ```bash
69
+ if command -v portless >/dev/null 2>&1; then portless list; fi
70
+ ```
71
+
72
+ Do not install Portless, start/stop proxies, trust CAs, sync hosts, prune/clean state, or expose LAN services from `/status`.
73
+
65
74
  ```typescript
66
75
  find_sessions({ query: "<project-name or recent-bead-keywords>", limit: 5 });
67
76
  ```
@@ -13,6 +13,7 @@ model: proxypal/gemini-3-pro-preview
13
13
  skill({ name: "visual-analysis" }); // Analysis framework
14
14
  skill({ name: "accessibility-audit" }); // WCAG checklists
15
15
  skill({ name: "frontend-design" }); // Anti-patterns, design quality
16
+ skill({ name: "ux-quality-gates" }); // IA, heuristics, forms, recovery, state coverage
16
17
  ```
17
18
 
18
19
  ## Input
@@ -33,31 +34,50 @@ Use the `visual-analysis` skill to perform deep analysis:
33
34
  - Visual properties (colors, typography, spacing, layout)
34
35
  - Design patterns and potential issues
35
36
 
36
- ### 2. Score Categories
37
+ ### 2. Usability Heuristic Pass
37
38
 
38
- Rate each 1-10 with brief justification:
39
+ Apply `ux-quality-gates` before visual scoring. Check:
40
+
41
+ - System status is visible for async or multi-step work
42
+ - Labels and navigation use user vocabulary, not implementation terms
43
+ - Users can cancel, undo, go back, retry, or recover from failure
44
+ - Controls, names, and layouts are consistent across the surface
45
+ - Dangerous or invalid actions are prevented before they happen
46
+ - Options and relationships are visible without relying on memory
47
+ - High-volume workflows expose efficient paths where appropriate
48
+ - Empty/loading/error/success states are present and useful
49
+
50
+ Any failure that blocks task completion or recovery is **Critical**, even if the screen looks polished.
39
51
 
40
- | Category | What to Evaluate |
41
- | ---------------------- | -------------------------------------------------------------- |
42
- | **Typography** | Hierarchy, readability, weight contrast, intentional choices |
43
- | **Color** | Palette cohesion, contrast, semantic usage, no AI slop |
44
- | **Layout & Spacing** | Visual hierarchy, consistency, alignment, white space |
45
- | **Interactive States** | Hover, focus, active, disabled, loading coverage |
46
- | **Accessibility** | WCAG AA compliance (use `accessibility-audit` skill checklist) |
47
- | **Visual Polish** | Consistency, attention to detail, motion, shadows, icons |
52
+ ### 3. Score Categories
53
+
54
+ Rate each 1-10 with brief justification:
48
55
 
49
- ### 3. Conditional Reviews
56
+ | Category | What to Evaluate |
57
+ | --------------------------------- | -------------------------------------------------------------- |
58
+ | **Information Architecture** | User vocabulary, scope clarity, relationships, navigation |
59
+ | **Task Flow & Recovery** | Primary action, cancellation, undo/retry, error recovery |
60
+ | **Forms & Data Interaction** | Labels, helper text, validation, selection, bulk actions |
61
+ | **Typography** | Hierarchy, readability, weight contrast, intentional choices |
62
+ | **Color** | Palette cohesion, contrast, semantic usage, no AI slop |
63
+ | **Layout & Spacing** | Visual hierarchy, consistency, alignment, white space |
64
+ | **Interactive States** | Hover, focus, active, disabled, loading/error/success coverage |
65
+ | **Accessibility & Semantic HTML** | WCAG AA compliance, native semantics, keyboard/focus behavior |
66
+ | **Component Consistency** | Shared token DNA: radius, height, border, shadow, states |
67
+ | **Visual Polish** | Consistency, attention to detail, motion, shadows, icons |
68
+
69
+ ### 4. Conditional Reviews
50
70
 
51
71
  **If `--responsive`**: Check at 375px, 768px, 1280px, 1536px+. Flag touch targets, horizontal scroll, text sizing.
52
72
 
53
73
  **If `--dark-mode`**: Check contrast on dark backgrounds, adapted colors (not just inverted), shadow adjustments, focus visibility.
54
74
 
55
- ### 4. Report Findings
75
+ ### 5. Report Findings
56
76
 
57
77
  Group by severity:
58
78
 
59
- - **Critical (Must Fix)**: Accessibility failures, broken interactions
60
- - **Warning (Should Fix)**: AI slop patterns, inconsistent spacing, missing states
79
+ - **Critical (Must Fix)**: Accessibility failures, broken interactions, dead-end errors, unsafe destructive actions
80
+ - **Warning (Should Fix)**: AI slop patterns, inconsistent spacing, missing states, confusing IA/naming
61
81
  - **Info (Nice to Have)**: Polish opportunities
62
82
 
63
83
  For each finding: location, impact, and recommended fix.
@@ -85,7 +105,7 @@ observation({
85
105
 
86
106
  ## Related Commands
87
107
 
88
- | Need | Command |
89
- | -------------------- | --------- |
90
- | Design from scratch | `/design` |
91
- | Ship implementation | `/ship` |
108
+ | Need | Command |
109
+ | ------------------- | --------- |
110
+ | Design from scratch | `/design` |
111
+ | Ship implementation | `/ship` |
@@ -15,16 +15,17 @@ Run a focused anti-slop audit against changed UI files using the frontend-design
15
15
  skill({ name: "frontend-design" }); // Anti-pattern taxonomy + design references
16
16
  skill({ name: "visual-analysis" }); // Structured visual/code analysis workflow
17
17
  skill({ name: "accessibility-audit" }); // Keyboard/focus/contrast checks
18
+ skill({ name: "ux-quality-gates" }); // UX correctness gates beyond visual slop
18
19
  ```
19
20
 
20
21
  ## Parse Arguments
21
22
 
22
- | Argument | Default | Description |
23
- | --------------- | ------- | ------------------------------------------------------------- |
24
- | `[path\|auto]` | `auto` | Specific file/dir to audit, or auto-detect changed UI files |
25
- | `--staged` | false | Audit staged changes only (`git diff --cached`) |
26
- | `--since=<ref>` | `HEAD` | Compare against ref (`main`, `HEAD~1`, commit SHA) |
27
- | `--full-report` | false | Include all categories even when no issues found |
23
+ | Argument | Default | Description |
24
+ | --------------- | ------- | ----------------------------------------------------------- |
25
+ | `[path\|auto]` | `auto` | Specific file/dir to audit, or auto-detect changed UI files |
26
+ | `--staged` | false | Audit staged changes only (`git diff --cached`) |
27
+ | `--since=<ref>` | `HEAD` | Compare against ref (`main`, `HEAD~1`, commit SHA) |
28
+ | `--full-report` | false | Include all categories even when no issues found |
28
29
 
29
30
  ## Phase 1: Resolve Target Files
30
31
 
@@ -96,12 +97,34 @@ Evaluate each target file (or rendered screenshot if provided) against these che
96
97
  - Error copy includes what happened + why + how to fix
97
98
  - Empty states include guidance + next action
98
99
  - Terminology is consistent (avoid mixed synonyms for same action)
100
+ - User-facing labels avoid implementation terms, database names, and internal acronyms
99
101
 
100
- ### F) Accessibility Safety Nets
102
+ ### F) UX Quality Gates
103
+
104
+ - One dominant filled primary action per view/section
105
+ - Destructive actions require explicit confirm or undo, with specific entity/count in copy
106
+ - No placeholder-as-label form fields
107
+ - Form errors are associated with controls (`aria-describedby`, `aria-invalid`, `role="alert"`)
108
+ - Submit/loading states prevent double-submit without layout shift
109
+ - Empty, loading, error, and success states exist where async/data flows exist
110
+ - Error toasts/banners persist long enough and include retry/undo/support where applicable
111
+ - Data-heavy UI distinguishes empty state from filtered no-results state
112
+ - Bulk actions show selected count and confirm destructive scope
113
+
114
+ ### G) Accessibility Safety Nets
101
115
 
102
116
  - Keyboard-visible focus treatment (`:focus-visible`)
103
117
  - Contrast baseline expectations (WCAG AA)
104
118
  - Touch targets reasonable (44x44 context where applicable)
119
+ - Native semantic elements are used before ARIA patches (`button`, `a`, `form`, landmarks)
120
+ - Heading structure has one logical `h1` per page/screen context
121
+
122
+ ### H) Component Family Consistency
123
+
124
+ - Buttons and inputs in the same form share height, radius, border, and focus treatment
125
+ - Focus, error, disabled, and loading states use the same token logic across components
126
+ - No one-off radius/shadow/border width unless documented as a system-level exception
127
+ - Semantic color roles are consistent: success, warning, destructive, info, primary
105
128
 
106
129
  ## Phase 3: Severity and Scoring
107
130
 
@@ -13,6 +13,7 @@ Check implementation against PRD before shipping.
13
13
  ```typescript
14
14
  skill({ name: "beads" });
15
15
  skill({ name: "verification-before-completion" });
16
+ // If local web/browser verification needs stable URLs: skill({ name: "portless" });
16
17
  ```
17
18
 
18
19
  ## Parse Arguments
@@ -105,6 +106,8 @@ Follow the [Verification Protocol](../skill/verification-before-completion/refer
105
106
  1. **Parallel**: typecheck + lint (simultaneously)
106
107
  2. **Sequential** (after parallel passes): test, then build (ship only)
107
108
 
109
+ For browser/manual local-web requirements, load the [portless](../skill/portless/SKILL.md) skill when stable named URLs would improve verification. Use only read-only Portless commands unless the user explicitly approves local networking changes; a reachable Portless URL supplements, but never replaces, typecheck/lint/test/build evidence.
110
+
108
111
  Report results with mode column:
109
112
 
110
113
  ```text
Binary file
@@ -84,6 +84,21 @@ function normalizeDomain(url: string): string {
84
84
  return url.replace(/^https?:\/\//, "").replace(/\/$/, "");
85
85
  }
86
86
 
87
+ const DEFAULT_COPILOT_API_BASE = "https://api.githubcopilot.com";
88
+
89
+ function toCopilotMessagesBase(url: string | undefined): string {
90
+ const base = (url?.trim() || DEFAULT_COPILOT_API_BASE)
91
+ .replace(/\/+$/, "")
92
+ .replace(/\/v1$/, "");
93
+ return `${base}/v1`;
94
+ }
95
+
96
+ function isClaudeCopilotModel(modelId: string, model: any): boolean {
97
+ return [modelId, model?.id, model?.api?.id]
98
+ .filter((value): value is string => typeof value === "string")
99
+ .some((value) => value.toLowerCase().includes("claude"));
100
+ }
101
+
87
102
  function getUrls(domain: string) {
88
103
  return {
89
104
  DEVICE_CODE_URL: `https://${domain}/login/device/code`,
@@ -565,7 +580,7 @@ export const CopilotAuthPlugin: Plugin = async ({ client: sdk, directory }) => {
565
580
  : undefined;
566
581
 
567
582
  if (provider && provider.models) {
568
- for (const [_modelId, model] of Object.entries(provider.models)) {
583
+ for (const [modelId, model] of Object.entries(provider.models)) {
569
584
  model.cost = {
570
585
  input: 0,
571
586
  output: 0,
@@ -575,9 +590,18 @@ export const CopilotAuthPlugin: Plugin = async ({ client: sdk, directory }) => {
575
590
  },
576
591
  };
577
592
 
578
- // Route all Copilot models through the local file-based SDK.
579
- // OpenCode's built-in github-copilot model loader will automatically
580
- // choose sdk.responses(model) for GPT-5+ and sdk.chat(model) otherwise.
593
+ // OpenCode 1.14.33 routes Copilot Claude models through the
594
+ // Anthropic Messages API when Copilot /models reports /v1/messages.
595
+ // Keep that route: the local OpenAI-compatible SDK calls
596
+ // /chat/completions, which returns 404 for current Claude models.
597
+ if (isClaudeCopilotModel(modelId, model)) {
598
+ model.api.npm = "@ai-sdk/anthropic";
599
+ model.api.url = toCopilotMessagesBase(baseURL ?? model.api.url);
600
+ continue;
601
+ }
602
+
603
+ // Route OpenAI-compatible Copilot models through the local file-based
604
+ // SDK so GPT/Gemini keep the reasoning_opaque and Responses fixes.
581
605
  model.api.npm = localCopilotSdk;
582
606
  }
583
607
  }
@@ -872,45 +896,40 @@ export const CopilotAuthPlugin: Plugin = async ({ client: sdk, directory }) => {
872
896
  const toolSource = modifiedBody || body;
873
897
  if (Array.isArray(toolSource?.tools)) {
874
898
  let toolsChanged = false;
875
- const sanitizedTools = toolSource.tools.map(
876
- (tool: any) => {
877
- if (!tool || typeof tool !== "object") return tool;
878
-
879
- let result = tool;
880
-
881
- // Strip top-level non-standard fields from tool object
882
- if (
883
- "custom" in result ||
884
- "eager_input_streaming" in result
885
- ) {
886
- toolsChanged = true;
887
- const {
888
- custom: _custom,
889
- eager_input_streaming: _eis,
890
- ...clean
891
- } = result;
892
- result = clean;
893
- }
899
+ const sanitizedTools = toolSource.tools.map((tool: any) => {
900
+ if (!tool || typeof tool !== "object") return tool;
901
+
902
+ let result = tool;
903
+
904
+ // Strip top-level non-standard fields from tool object
905
+ if ("custom" in result || "eager_input_streaming" in result) {
906
+ toolsChanged = true;
907
+ const {
908
+ custom: _custom,
909
+ eager_input_streaming: _eis,
910
+ ...clean
911
+ } = result;
912
+ result = clean;
913
+ }
894
914
 
895
- // Also check nested function object (Chat Completions format)
896
- if (
897
- result.function &&
898
- typeof result.function === "object" &&
899
- ("custom" in result.function ||
900
- "eager_input_streaming" in result.function)
901
- ) {
902
- toolsChanged = true;
903
- const {
904
- custom: _c,
905
- eager_input_streaming: _e,
906
- ...cleanFn
907
- } = result.function;
908
- result = { ...result, function: cleanFn };
909
- }
915
+ // Also check nested function object (Chat Completions format)
916
+ if (
917
+ result.function &&
918
+ typeof result.function === "object" &&
919
+ ("custom" in result.function ||
920
+ "eager_input_streaming" in result.function)
921
+ ) {
922
+ toolsChanged = true;
923
+ const {
924
+ custom: _c,
925
+ eager_input_streaming: _e,
926
+ ...cleanFn
927
+ } = result.function;
928
+ result = { ...result, function: cleanFn };
929
+ }
910
930
 
911
- return result;
912
- },
913
- );
931
+ return result;
932
+ });
914
933
 
915
934
  if (toolsChanged) {
916
935
  modifiedBody = {
@@ -1248,6 +1267,12 @@ export const CopilotAuthPlugin: Plugin = async ({ client: sdk, directory }) => {
1248
1267
  "chat.params": async (input: any, output: any) => {
1249
1268
  if (!input.model?.providerID?.includes("github-copilot")) return;
1250
1269
 
1270
+ // Copilot rejects eager tool streaming on Anthropic Messages routing.
1271
+ if (input.model?.api?.npm === "@ai-sdk/anthropic") {
1272
+ output.options ??= {};
1273
+ output.options.toolStreaming = false;
1274
+ }
1275
+
1251
1276
  // GPT models don't support maxOutputTokens through the Copilot proxy
1252
1277
  if (input.model?.api?.id?.includes("gpt")) {
1253
1278
  output.maxOutputTokens = undefined;