opencodekit 0.19.6 → 0.20.1

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 (55) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/template/.opencode/dcp-prompts/defaults/compress-message.md +1 -0
  3. package/dist/template/.opencode/memory.db +0 -0
  4. package/dist/template/.opencode/memory.db-shm +0 -0
  5. package/dist/template/.opencode/memory.db-wal +0 -0
  6. package/dist/template/.opencode/opencode.json +2 -2
  7. package/dist/template/.opencode/plugin/copilot-auth.ts +161 -53
  8. package/dist/template/.opencode/skill/chrome-devtools/SKILL.md +1 -1
  9. package/dist/template/.opencode/skill/cloudflare/SKILL.md +1 -1
  10. package/dist/template/.opencode/skill/context-management/SKILL.md +306 -79
  11. package/dist/template/.opencode/skill/core-data-expert/SKILL.md +1 -1
  12. package/dist/template/.opencode/skill/design-system-audit/SKILL.md +1 -1
  13. package/dist/template/.opencode/skill/design-taste-frontend/SKILL.md +1 -1
  14. package/dist/template/.opencode/skill/figma/SKILL.md +1 -1
  15. package/dist/template/.opencode/skill/figma-go/SKILL.md +1 -1
  16. package/dist/template/.opencode/skill/frontend-design/SKILL.md +1 -1
  17. package/dist/template/.opencode/skill/full-output-enforcement/SKILL.md +1 -1
  18. package/dist/template/.opencode/skill/high-end-visual-design/SKILL.md +1 -1
  19. package/dist/template/.opencode/skill/index-knowledge/SKILL.md +1 -1
  20. package/dist/template/.opencode/skill/industrial-brutalist-ui/SKILL.md +1 -1
  21. package/dist/template/.opencode/skill/jira/SKILL.md +1 -1
  22. package/dist/template/.opencode/skill/minimalist-ui/SKILL.md +1 -1
  23. package/dist/template/.opencode/skill/mqdh/SKILL.md +1 -1
  24. package/dist/template/.opencode/skill/opensrc/SKILL.md +184 -27
  25. package/dist/template/.opencode/skill/pdf-extract/SKILL.md +1 -1
  26. package/dist/template/.opencode/skill/pencil/SKILL.md +1 -1
  27. package/dist/template/.opencode/skill/playwright/SKILL.md +18 -6
  28. package/dist/template/.opencode/skill/{agent-browser/SKILL.md → playwright/references/agent-browser-cli.md} +0 -8
  29. package/dist/template/.opencode/skill/playwriter/SKILL.md +1 -1
  30. package/dist/template/.opencode/skill/polar/SKILL.md +1 -1
  31. package/dist/template/.opencode/skill/prd/SKILL.md +1 -1
  32. package/dist/template/.opencode/skill/react-best-practices/SKILL.md +1 -1
  33. package/dist/template/.opencode/skill/redesign-existing-projects/SKILL.md +1 -1
  34. package/dist/template/.opencode/skill/resend/SKILL.md +1 -1
  35. package/dist/template/.opencode/skill/stitch/SKILL.md +1 -1
  36. package/dist/template/.opencode/skill/stitch-design-taste/SKILL.md +1 -1
  37. package/dist/template/.opencode/skill/supabase/SKILL.md +1 -1
  38. package/dist/template/.opencode/skill/supabase-postgres-best-practices/SKILL.md +1 -1
  39. package/dist/template/.opencode/skill/v0/SKILL.md +1 -1
  40. package/dist/template/.opencode/skill/v1-run/SKILL.md +1 -1
  41. package/dist/template/.opencode/skill/webclaw/SKILL.md +1 -1
  42. package/dist/template/.opencode/skill/writing-skills/SKILL.md +43 -6
  43. package/dist/template/.opencode/skill/{testing-skills-with-subagents/SKILL.md → writing-skills/references/testing-methodology.md} +0 -8
  44. package/package.json +1 -1
  45. package/dist/template/.opencode/skill/compaction/SKILL.md +0 -384
  46. package/dist/template/.opencode/skill/session-management/SKILL.md +0 -9
  47. package/dist/template/.opencode/skill/source-code-research/SKILL.md +0 -293
  48. package/dist/template/.opencode/skill/ui-ux-research/SKILL.md +0 -9
  49. package/dist/template/.opencode/skill/using-skills/SKILL.md +0 -117
  50. /package/dist/template/.opencode/skill/{source-code-research → opensrc}/references/analysis-tips.md +0 -0
  51. /package/dist/template/.opencode/skill/{source-code-research → opensrc}/references/anti-patterns.md +0 -0
  52. /package/dist/template/.opencode/skill/{source-code-research → opensrc}/references/common-patterns.md +0 -0
  53. /package/dist/template/.opencode/skill/{source-code-research → opensrc}/references/example-workflow.md +0 -0
  54. /package/dist/template/.opencode/skill/{source-code-research → opensrc}/references/further-reading.md +0 -0
  55. /package/dist/template/.opencode/skill/{source-code-research → opensrc}/references/source-structure.md +0 -0
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
20
20
 
21
21
  //#endregion
22
22
  //#region package.json
23
- var version = "0.19.6";
23
+ var version = "0.20.1";
24
24
 
25
25
  //#endregion
26
26
  //#region src/utils/license.ts
@@ -39,3 +39,4 @@ During general cleanup, compress all medium and high-priority messages that are
39
39
  Optimize for reducing context footprint, not for grouping messages by topic.
40
40
  Do not compress away still-active instructions, unresolved questions, or constraints that are likely to matter soon.
41
41
  Prioritize the earliest messages in the context as they will be the least relevant to the active task.
42
+ General cleanup should be done periodically between other normal compression tool passes, not as the primary form of compression.
Binary file
@@ -85,8 +85,8 @@
85
85
  ".opencode/context/git-context.md"
86
86
  ],
87
87
  "keybinds": {
88
- "leader": "`",
89
- "session_parent": "<leader>up"
88
+ "leader": "ctrl+x",
89
+ "session_parent": "up"
90
90
  },
91
91
  "mcp": {
92
92
  "tilth": {
@@ -94,6 +94,51 @@ function getUrls(domain: string) {
94
94
 
95
95
  const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
96
96
 
97
+ function getRequestUrl(input: RequestInfo | URL): string {
98
+ if (typeof input === "string") return input;
99
+ if (input instanceof URL) return input.toString();
100
+ if (typeof Request !== "undefined" && input instanceof Request) {
101
+ return input.url;
102
+ }
103
+ return input.toString();
104
+ }
105
+
106
+ function extractClaudeThinkingBudget(body: any): number | undefined {
107
+ const candidates = [body?.thinking_budget, body?.thinking?.budget_tokens];
108
+
109
+ for (const candidate of candidates) {
110
+ if (typeof candidate === "number" && Number.isFinite(candidate)) {
111
+ const normalized = Math.trunc(candidate);
112
+ if (normalized > 0) return normalized;
113
+ }
114
+ }
115
+
116
+ return undefined;
117
+ }
118
+
119
+ function getErrorMessage(error: unknown): string {
120
+ if (error instanceof Error) return error.message;
121
+ if (typeof error === "string") return error;
122
+ try {
123
+ return JSON.stringify(error);
124
+ } catch {
125
+ return String(error);
126
+ }
127
+ }
128
+
129
+ function isTransientUpstreamTimeoutError(error: unknown): boolean {
130
+ const message = getErrorMessage(error).toLowerCase();
131
+ return (
132
+ message.includes("upstream idle timeout") ||
133
+ message.includes("mid_stream") ||
134
+ message.includes("sse read timed out") ||
135
+ message.includes("socket connection was closed unexpectedly") ||
136
+ message.includes("connection reset") ||
137
+ message.includes("econnreset") ||
138
+ message.includes("etimedout")
139
+ );
140
+ }
141
+
97
142
  // Rate limit handling configuration
98
143
  const RATE_LIMIT_CONFIG = {
99
144
  maxDelayMs: 60000, // Cap at 60 seconds
@@ -553,7 +598,7 @@ export const CopilotAuthPlugin: Plugin = async ({ client: sdk }) => {
553
598
  ? JSON.parse(init.body)
554
599
  : init?.body;
555
600
 
556
- const url = input.toString();
601
+ const url = getRequestUrl(input);
557
602
 
558
603
  // Check if this is a Claude model request
559
604
  const modelId = body?.model || "";
@@ -574,18 +619,34 @@ export const CopilotAuthPlugin: Plugin = async ({ client: sdk }) => {
574
619
  // For Claude models, add thinking_budget to enable reasoning
575
620
  // The Copilot API accepts this parameter and returns reasoning_text/reasoning_opaque
576
621
  if (isClaudeModel) {
577
- // Use configured thinking_budget from model options, or default to 10000
578
- const thinkingBudget = body.thinking_budget || 10000;
579
-
580
- // Fix for "Invalid signature in thinking block" error:
581
- // The Copilot API uses reasoning_text/reasoning_opaque format for thinking
582
- // When these are passed back without proper signature, it causes errors
583
- // Solution: Ensure reasoning_opaque is present when reasoning_text exists,
584
- // or remove reasoning content entirely if signature is invalid/missing
622
+ const thinkingBudget = extractClaudeThinkingBudget(body);
623
+ const isThinkingEnabled = thinkingBudget != null;
624
+
585
625
  const cleanedMessages = body.messages.map(
586
626
  (msg: any, idx: number) => {
587
627
  if (msg.role !== "assistant") return msg;
588
628
 
629
+ // If thinking is disabled, strip all reasoning metadata to prevent
630
+ // stale reasoning context from continuing across turns.
631
+ if (!isThinkingEnabled) {
632
+ const {
633
+ reasoning_text: _reasoningText,
634
+ reasoning_opaque: _reasoningOpaque,
635
+ ...baseMsg
636
+ } = msg;
637
+ if (!Array.isArray(baseMsg.content)) return baseMsg;
638
+
639
+ const cleanedContent = baseMsg.content.filter(
640
+ (part: any) => part.type !== "thinking",
641
+ );
642
+
643
+ return {
644
+ ...baseMsg,
645
+ content:
646
+ cleanedContent.length > 0 ? cleanedContent : null,
647
+ };
648
+ }
649
+
589
650
  // Log message structure for debugging
590
651
  log("debug", `Processing assistant message ${idx}`, {
591
652
  has_reasoning_text: !!msg.reasoning_text,
@@ -605,11 +666,6 @@ export const CopilotAuthPlugin: Plugin = async ({ client: sdk }) => {
605
666
  }
606
667
 
607
668
  // If content is an array, strip ALL thinking blocks.
608
- // Reasoning is communicated via reasoning_text/reasoning_opaque
609
- // fields, not via thinking blocks in the content array.
610
- // Even thinking blocks WITH signatures can cause
611
- // "Invalid signature in thinking block" errors when
612
- // signatures are expired or from a different context.
613
669
  if (Array.isArray(msg.content)) {
614
670
  const hasThinkingBlock = msg.content.some(
615
671
  (part: any) => part.type === "thinking",
@@ -634,15 +690,31 @@ export const CopilotAuthPlugin: Plugin = async ({ client: sdk }) => {
634
690
  },
635
691
  );
636
692
 
637
- modifiedBody = {
638
- ...body,
693
+ const nextBody: Record<string, any> = {
694
+ ...(modifiedBody || body),
639
695
  messages: cleanedMessages,
640
- thinking_budget: thinkingBudget,
641
696
  };
642
- log("info", `Adding thinking_budget for Claude model`, {
643
- model: modelId,
644
- thinking_budget: thinkingBudget,
645
- });
697
+
698
+ if (isThinkingEnabled) {
699
+ nextBody.thinking_budget = thinkingBudget;
700
+ log("info", `Adding thinking_budget for Claude model`, {
701
+ model: modelId,
702
+ thinking_budget: thinkingBudget,
703
+ });
704
+ } else {
705
+ delete nextBody.thinking_budget;
706
+ log(
707
+ "info",
708
+ `Claude thinking disabled for this request (no thinking budget set)`,
709
+ { model: modelId },
710
+ );
711
+ }
712
+
713
+ // Copilot OpenAI-compatible endpoint expects `thinking_budget`.
714
+ // Remove Anthropic-style `thinking` object to avoid mixed payloads.
715
+ delete nextBody.thinking;
716
+
717
+ modifiedBody = nextBody;
646
718
  }
647
719
 
648
720
  // For GPT models (o1, gpt-5, etc.), add reasoning parameter
@@ -839,46 +911,82 @@ export const CopilotAuthPlugin: Plugin = async ({ client: sdk }) => {
839
911
  }
840
912
  }
841
913
 
842
- try {
843
- if (currentModel) {
844
- await shapeRequestForModel(currentModel);
845
- }
846
- const response = await fetch(input, activeFinalInit);
914
+ const maxFetchAttempts = 2;
847
915
 
848
- if (response.status === 429) {
849
- try {
850
- await response.body?.cancel();
851
- } catch {}
916
+ for (let attempt = 1; attempt <= maxFetchAttempts; attempt++) {
917
+ try {
918
+ if (currentModel) {
919
+ await shapeRequestForModel(currentModel);
920
+ }
921
+ const response = await fetch(input, activeFinalInit);
852
922
 
853
- const retryAfterMs = parseRetryAfter(response);
854
- const cooldownMs = clampCooldownMs(
855
- retryAfterMs,
856
- RATE_LIMIT_CONFIG.defaultCooldownMs,
857
- );
923
+ if (response.status === 429) {
924
+ try {
925
+ await response.body?.cancel();
926
+ } catch {}
858
927
 
859
- if (currentModel) {
860
- markModelRateLimited(currentModel, cooldownMs);
861
- openFamilyCircuitBreaker(currentModel, cooldownMs);
928
+ const retryAfterMs = parseRetryAfter(response);
929
+ const cooldownMs = clampCooldownMs(
930
+ retryAfterMs,
931
+ RATE_LIMIT_CONFIG.defaultCooldownMs,
932
+ );
933
+
934
+ if (currentModel) {
935
+ markModelRateLimited(currentModel, cooldownMs);
936
+ openFamilyCircuitBreaker(currentModel, cooldownMs);
937
+ }
938
+
939
+ throw new Error(
940
+ `[Copilot] Rate limited: ${currentModel || "model"} cooling down. Retry in ${formatRetryAfter(Math.ceil(cooldownMs / 1000))}.`,
941
+ );
862
942
  }
863
943
 
864
- throw new Error(
865
- `[Copilot] Rate limited: ${currentModel || "model"} cooling down. Retry in ${formatRetryAfter(Math.ceil(cooldownMs / 1000))}.`,
866
- );
867
- }
944
+ // Response transformation is handled by the custom SDK at
945
+ // .opencode/plugin/sdk/copilot/
946
+ return response;
947
+ } catch (error) {
948
+ const errorMessage = getErrorMessage(error);
949
+ if (
950
+ errorMessage.includes("Rate limited") ||
951
+ errorMessage.includes("Local request queue saturated")
952
+ ) {
953
+ throw error instanceof Error
954
+ ? error
955
+ : new Error(errorMessage);
956
+ }
957
+
958
+ if (
959
+ attempt < maxFetchAttempts &&
960
+ isTransientUpstreamTimeoutError(error)
961
+ ) {
962
+ const retryDelayMs = 750 * attempt;
963
+ log(
964
+ "warn",
965
+ `Transient upstream timeout from Copilot, retrying request`,
966
+ {
967
+ model: currentModel || undefined,
968
+ attempt,
969
+ retry_delay_ms: retryDelayMs,
970
+ error: errorMessage,
971
+ },
972
+ );
973
+ await sleep(retryDelayMs);
974
+ continue;
975
+ }
868
976
 
869
- // Response transformation is handled by the custom SDK at
870
- // .opencode/plugin/sdk/copilot/
871
- return response;
872
- } catch (error) {
873
- const lastError = error as Error;
874
- if (
875
- lastError.message.includes("Rate limited") ||
876
- lastError.message.includes("Local request queue saturated")
877
- ) {
878
- throw lastError;
977
+ if (isTransientUpstreamTimeoutError(error)) {
978
+ throw new Error(
979
+ `[Copilot] Upstream idle timeout while streaming ${currentModel || "request"}. Retry with a lower thinking budget or switch to a lower-latency Claude variant.`,
980
+ );
981
+ }
982
+
983
+ throw error;
879
984
  }
880
- throw error;
881
985
  }
986
+
987
+ throw new Error(
988
+ `[Copilot] Failed request after ${maxFetchAttempts} attempts.`,
989
+ );
882
990
  },
883
991
  };
884
992
  },
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: chrome-devtools
3
- description: Chrome DevTools for debugging, performance analysis, and browser automation. Use when debugging web apps, analyzing performance, inspecting network requests, or automating browser interactions.
3
+ description: Use when debugging web apps in Chrome performance profiling, network inspection, DOM debugging, or console automation. MUST load before any Chrome DevTools-based debugging session.
4
4
  version: 1.0.0
5
5
  tags: [automation, debugging]
6
6
  dependencies: []
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: cloudflare
3
- description: Comprehensive Cloudflare platform skill covering Workers, Pages, storage (KV, D1, R2), AI (Workers AI, Vectorize, Agents SDK), networking (Tunnel, Spectrum), security (WAF, DDoS), and infrastructure-as-code (Terraform, Pulumi). Use for any Cloudflare development task.
3
+ description: Use when deploying to or configuring ANY Cloudflare service Workers, Pages, KV, D1, R2, AI, Tunnel, WAF. MUST load before writing Cloudflare Workers code, wrangler configs, or infrastructure-as-code for Cloudflare.
4
4
  references:
5
5
  - workers
6
6
  - pages