oh-my-opencode 2.6.2 → 2.7.0
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.
- package/README.ja.md +3 -3
- package/README.ko.md +3 -3
- package/README.md +3 -3
- package/README.zh-cn.md +3 -3
- package/dist/auth/antigravity/project.d.ts +1 -0
- package/dist/auth/antigravity/token.d.ts +17 -20
- package/dist/auth/antigravity/types.d.ts +19 -0
- package/dist/cli/index.js +10 -4
- package/dist/config/index.d.ts +2 -2
- package/dist/config/schema.d.ts +16 -2
- package/dist/features/builtin-commands/commands.d.ts +2 -0
- package/dist/features/builtin-commands/index.d.ts +2 -0
- package/dist/features/builtin-commands/templates/init-deep.d.ts +1 -0
- package/dist/features/builtin-commands/types.d.ts +6 -0
- package/dist/google-auth.js +152 -22
- package/dist/hooks/comment-checker/cli.d.ts +2 -1
- package/dist/hooks/comment-checker/index.d.ts +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1318 -609
- package/dist/shared/data-path.d.ts +6 -7
- package/dist/tools/ast-grep/constants.d.ts +0 -1
- package/dist/tools/lsp/client.d.ts +1 -2
- package/dist/tools/lsp/config.d.ts +2 -9
- package/dist/tools/lsp/constants.d.ts +1 -0
- package/dist/tools/lsp/types.d.ts +25 -0
- package/dist/tools/lsp/utils.d.ts +4 -1
- package/dist/tools/session-manager/storage.d.ts +5 -5
- package/dist/tools/session-manager/utils.d.ts +3 -3
- package/package.json +2 -2
package/README.ja.md
CHANGED
|
@@ -396,8 +396,8 @@ gh repo star code-yeongyu/oh-my-opencode
|
|
|
396
396
|
|
|
397
397
|
- **Sisyphus** (`anthropic/claude-opus-4-5`): **デフォルトエージェントです。** OpenCode のための強力な AI オーケストレーターです。専門のサブエージェントを活用して、複雑なタスクを計画、委任、実行します。バックグラウンドタスクへの委任と Todo ベースのワークフローを重視します。最大の推論能力を発揮するため、Claude Opus 4.5 と拡張思考 (32k token budget) を使用します。
|
|
398
398
|
- **oracle** (`openai/gpt-5.2`): アーキテクチャ、コードレビュー、戦略立案のための専門アドバイザー。GPT-5.2 の卓越した論理的推論と深い分析能力を活用します。AmpCode からインスピレーションを得ました。
|
|
399
|
-
- **librarian** (`anthropic/claude-sonnet-4-5`): マルチリポジトリ分析、ドキュメント検索、実装例の調査を担当。Claude Sonnet 4.5 を使用して、深いコードベース理解と GitHub リサーチ、根拠に基づいた回答を提供します。AmpCode からインスピレーションを得ました。
|
|
400
|
-
- **explore** (`opencode/grok-code`): 高速なコードベース探索、ファイルパターンマッチング。Claude
|
|
399
|
+
- **librarian** (`anthropic/claude-sonnet-4-5` または `google/gemini-3-flash`): マルチリポジトリ分析、ドキュメント検索、実装例の調査を担当。Antigravity 認証が設定されている場合は Gemini 3 Flash を使用し、それ以外は Claude Sonnet 4.5 を使用して、深いコードベース理解と GitHub リサーチ、根拠に基づいた回答を提供します。AmpCode からインスピレーションを得ました。
|
|
400
|
+
- **explore** (`opencode/grok-code`、`google/gemini-3-flash`、または `anthropic/claude-haiku-4-5`): 高速なコードベース探索、ファイルパターンマッチング。Antigravity 認証が設定されている場合は Gemini 3 Flash を使用し、Claude max20 が利用可能な場合は Haiku を使用し、それ以外は Grok を使います。Claude Code からインスピレーションを得ました。
|
|
401
401
|
- **frontend-ui-ux-engineer** (`google/gemini-3-pro-preview`): 開発者に転身したデザイナーという設定です。素晴らしい UI を作ります。美しく独創的な UI コードを生成することに長けた Gemini を使用します。
|
|
402
402
|
- **document-writer** (`google/gemini-3-pro-preview`): テクニカルライティングの専門家という設定です。Gemini は文筆家であり、流れるような文章を書きます。
|
|
403
403
|
- **multimodal-looker** (`google/gemini-3-flash`): 視覚コンテンツ解釈のための専門エージェント。PDF、画像、図表を分析して情報を抽出します。
|
|
@@ -857,7 +857,7 @@ OpenCode でサポートされるすべての LSP 構成およびカスタム設
|
|
|
857
857
|
| `aggressive_truncation` | `false` | トークン制限を超えた場合、ツール出力を積極的に切り詰めて制限内に収めます。デフォルトの切り詰めより積極的です。不十分な場合は要約/復元にフォールバックします。 |
|
|
858
858
|
| `auto_resume` | `false` | thinking block エラーや thinking disabled violation からの回復成功後、自動的にセッションを再開します。最後のユーザーメッセージを抽出して続行します。 |
|
|
859
859
|
| `truncate_all_tool_outputs` | `true` | プロンプトが長くなりすぎるのを防ぐため、コンテキストウィンドウの使用状況に基づいてすべてのツール出力を動的に切り詰めます。完全なツール出力が必要な場合は`false`に設定して無効化します。 |
|
|
860
|
-
| `
|
|
860
|
+
| `dcp_for_compaction` | `false` | 有効にすると、トークン制限エラー発生時にDCP(Dynamic Context Pruning)が最初に実行され、その後コンパクションが実行されます。DCPが不要なコンテキストを整理した後、すぐにコンパクションが進行します。トークン制限に達した際によりスマートな回復が必要な場合は有効にしてください。 |
|
|
861
861
|
|
|
862
862
|
**警告**:これらの機能は実験的であり、予期しない動作を引き起こす可能性があります。影響を理解した場合にのみ有効にしてください。
|
|
863
863
|
|
package/README.ko.md
CHANGED
|
@@ -393,8 +393,8 @@ gh repo star code-yeongyu/oh-my-opencode
|
|
|
393
393
|
|
|
394
394
|
- **Sisyphus** (`anthropic/claude-opus-4-5`): **기본 에이전트입니다.** OpenCode를 위한 강력한 AI 오케스트레이터입니다. 전문 서브에이전트를 활용하여 복잡한 작업을 계획, 위임, 실행합니다. 백그라운드 태스크 위임과 todo 기반 워크플로우를 강조합니다. 최대 추론 능력을 위해 Claude Opus 4.5와 확장된 사고(32k 버짓)를 사용합니다.
|
|
395
395
|
- **oracle** (`openai/gpt-5.2`): 아키텍처, 코드 리뷰, 전략 수립을 위한 전문가 조언자. GPT-5.2의 뛰어난 논리적 추론과 깊은 분석 능력을 활용합니다. AmpCode 에서 영감을 받았습니다.
|
|
396
|
-
- **librarian** (`anthropic/claude-sonnet-4-5`): 멀티 레포 분석, 문서 조회, 구현 예제 담당. Claude Sonnet 4.5를 사용하여 깊은 코드베이스 이해와 GitHub 조사, 근거 기반의 답변을 제공합니다. AmpCode 에서 영감을 받았습니다.
|
|
397
|
-
- **explore** (`opencode/grok-code`): 빠른 코드베이스 탐색, 파일 패턴 매칭.
|
|
396
|
+
- **librarian** (`anthropic/claude-sonnet-4-5` 또는 `google/gemini-3-flash`): 멀티 레포 분석, 문서 조회, 구현 예제 담당. Antigravity 인증이 설정된 경우 Gemini 3 Flash를 사용하고, 그렇지 않으면 Claude Sonnet 4.5를 사용하여 깊은 코드베이스 이해와 GitHub 조사, 근거 기반의 답변을 제공합니다. AmpCode 에서 영감을 받았습니다.
|
|
397
|
+
- **explore** (`opencode/grok-code`, `google/gemini-3-flash`, 또는 `anthropic/claude-haiku-4-5`): 빠른 코드베이스 탐색, 파일 패턴 매칭. Antigravity 인증이 설정된 경우 Gemini 3 Flash를 사용하고, Claude max20이 있으면 Haiku를 사용하며, 그 외에는 Grok을 씁니다. Claude Code 에서 영감을 받았습니다.
|
|
398
398
|
- **frontend-ui-ux-engineer** (`google/gemini-3-pro-preview`): 개발자로 전향한 디자이너라는 설정을 갖고 있습니다. 멋진 UI를 만듭니다. 아름답고 창의적인 UI 코드를 생성하는 데 탁월한 Gemini를 사용합니다.
|
|
399
399
|
- **document-writer** (`google/gemini-3-pro-preview`): 기술 문서 전문가라는 설정을 갖고 있습니다. Gemini 는 문학가입니다. 글을 기가막히게 씁니다.
|
|
400
400
|
- **multimodal-looker** (`google/gemini-3-flash`): 시각적 콘텐츠 해석을 위한 전문 에이전트. PDF, 이미지, 다이어그램을 분석하여 정보를 추출합니다.
|
|
@@ -851,7 +851,7 @@ OpenCode 에서 지원하는 모든 LSP 구성 및 커스텀 설정 (opencode.js
|
|
|
851
851
|
| `aggressive_truncation` | `false` | 토큰 제한을 초과하면 도구 출력을 공격적으로 잘라내어 제한 내에 맞춥니다. 기본 truncation보다 더 공격적입니다. 부족하면 요약/복구로 fallback합니다. |
|
|
852
852
|
| `auto_resume` | `false` | thinking block 에러나 thinking disabled violation으로부터 성공적으로 복구한 후 자동으로 세션을 재개합니다. 마지막 사용자 메시지를 추출하여 계속합니다. |
|
|
853
853
|
| `truncate_all_tool_outputs` | `true` | 프롬프트가 너무 길어지는 것을 방지하기 위해 컨텍스트 윈도우 사용량에 따라 모든 도구 출력을 동적으로 잘라냅니다. 전체 도구 출력이 필요한 경우 `false`로 설정하여 비활성화하세요. |
|
|
854
|
-
| `
|
|
854
|
+
| `dcp_for_compaction` | `false` | 활성화하면, 토큰 제한 에러 발생 시 DCP(Dynamic Context Pruning)가 가장 먼저 실행되고, 그 다음 compaction이 실행됩니다. DCP가 불필요한 컨텍스트를 정리한 후 바로 compaction이 진행됩니다. 토큰 제한에 도달했을 때 더 스마트한 복구를 원하면 활성화하세요. |
|
|
855
855
|
|
|
856
856
|
**경고**: 이 기능들은 실험적이며 예상치 못한 동작을 유발할 수 있습니다. 의미를 이해한 경우에만 활성화하세요.
|
|
857
857
|
|
package/README.md
CHANGED
|
@@ -465,8 +465,8 @@ To remove oh-my-opencode:
|
|
|
465
465
|
|
|
466
466
|
- **Sisyphus** (`anthropic/claude-opus-4-5`): **The default agent.** A powerful AI orchestrator for OpenCode. Plans, delegates, and executes complex tasks using specialized subagents with aggressive parallel execution. Emphasizes background task delegation and todo-driven workflow. Uses Claude Opus 4.5 with extended thinking (32k budget) for maximum reasoning capability.
|
|
467
467
|
- **oracle** (`openai/gpt-5.2`): Architecture, code review, strategy. Uses GPT-5.2 for its stellar logical reasoning and deep analysis. Inspired by AmpCode.
|
|
468
|
-
- **librarian** (`anthropic/claude-sonnet-4-5`): Multi-repo analysis, doc lookup, implementation examples. Uses Claude Sonnet 4.5 for deep codebase understanding and GitHub research with evidence-based answers. Inspired by AmpCode.
|
|
469
|
-
- **explore** (`opencode/grok-code`): Fast codebase exploration and pattern matching.
|
|
468
|
+
- **librarian** (`anthropic/claude-sonnet-4-5` or `google/gemini-3-flash`): Multi-repo analysis, doc lookup, implementation examples. Uses Gemini 3 Flash when Antigravity auth is configured, otherwise Claude Sonnet 4.5 for deep codebase understanding and GitHub research with evidence-based answers. Inspired by AmpCode.
|
|
469
|
+
- **explore** (`opencode/grok-code`, `google/gemini-3-flash`, or `anthropic/claude-haiku-4-5`): Fast codebase exploration and pattern matching. Uses Gemini 3 Flash when Antigravity auth is configured, Haiku when Claude max20 is available, otherwise Grok. Inspired by Claude Code.
|
|
470
470
|
- **frontend-ui-ux-engineer** (`google/gemini-3-pro-high`): A designer turned developer. Builds gorgeous UIs. Gemini excels at creative, beautiful UI code.
|
|
471
471
|
- **document-writer** (`google/gemini-3-flash`): Technical writing expert. Gemini is a wordsmith—writes prose that flows.
|
|
472
472
|
- **multimodal-looker** (`google/gemini-3-flash`): Visual content specialist. Analyzes PDFs, images, diagrams to extract information.
|
|
@@ -953,7 +953,7 @@ Opt-in experimental features that may change or be removed in future versions. U
|
|
|
953
953
|
| `aggressive_truncation` | `false` | When token limit is exceeded, aggressively truncates tool outputs to fit within limits. More aggressive than the default truncation behavior. Falls back to summarize/revert if insufficient. |
|
|
954
954
|
| `auto_resume` | `false` | Automatically resumes session after successful recovery from thinking block errors or thinking disabled violations. Extracts the last user message and continues. |
|
|
955
955
|
| `truncate_all_tool_outputs` | `true` | Dynamically truncates ALL tool outputs based on context window usage to prevent prompts from becoming too long. Disable by setting to `false` if you need full tool outputs. |
|
|
956
|
-
| `
|
|
956
|
+
| `dcp_for_compaction` | `false` | When enabled, Dynamic Context Pruning (DCP) runs FIRST when token limit errors occur, before attempting compaction. DCP prunes redundant context, then compaction runs immediately. Enable this for smarter recovery when hitting token limits. |
|
|
957
957
|
|
|
958
958
|
**Warning**: These features are experimental and may cause unexpected behavior. Enable only if you understand the implications.
|
|
959
959
|
|
package/README.zh-cn.md
CHANGED
|
@@ -404,8 +404,8 @@ gh repo star code-yeongyu/oh-my-opencode
|
|
|
404
404
|
|
|
405
405
|
- **Sisyphus** (`anthropic/claude-opus-4-5`):**默认 Agent。** OpenCode 专属的强力 AI 编排器。指挥专业子 Agent 搞定复杂任务。主打后台任务委派和 Todo 驱动。用 Claude Opus 4.5 加上扩展思考(32k token 预算),智商拉满。
|
|
406
406
|
- **oracle** (`openai/gpt-5.2`):架构师、代码审查员、战略家。GPT-5.2 的逻辑推理和深度分析能力不是盖的。致敬 AmpCode。
|
|
407
|
-
- **librarian** (`anthropic/claude-sonnet-4-5`)
|
|
408
|
-
- **explore** (`opencode/grok-code`)
|
|
407
|
+
- **librarian** (`anthropic/claude-sonnet-4-5` 或 `google/gemini-3-flash`):多仓库分析、查文档、找示例。配置 Antigravity 认证时使用 Gemini 3 Flash,否则使用 Claude Sonnet 4.5 深入理解代码库,GitHub 调研,给出的答案都有据可查。致敬 AmpCode。
|
|
408
|
+
- **explore** (`opencode/grok-code`、`google/gemini-3-flash` 或 `anthropic/claude-haiku-4-5`):极速代码库扫描、模式匹配。配置 Antigravity 认证时使用 Gemini 3 Flash,Claude max20 可用时使用 Haiku,否则用 Grok。致敬 Claude Code。
|
|
409
409
|
- **frontend-ui-ux-engineer** (`google/gemini-3-pro-preview`):设计师出身的程序员。UI 做得那是真漂亮。Gemini 写这种创意美观的代码是一绝。
|
|
410
410
|
- **document-writer** (`google/gemini-3-pro-preview`):技术写作专家。Gemini 文笔好,写出来的东西读着顺畅。
|
|
411
411
|
- **multimodal-looker** (`google/gemini-3-flash`):视觉内容专家。PDF、图片、图表,看一眼就知道里头有啥。
|
|
@@ -857,7 +857,7 @@ Oh My OpenCode 送你重构工具(重命名、代码操作)。
|
|
|
857
857
|
| `aggressive_truncation` | `false` | 超出 token 限制时,激进地截断工具输出以适应限制。比默认截断更激进。不够的话会回退到摘要/恢复。 |
|
|
858
858
|
| `auto_resume` | `false` | 从 thinking block 错误或 thinking disabled violation 成功恢复后,自动恢复会话。提取最后一条用户消息继续执行。 |
|
|
859
859
|
| `truncate_all_tool_outputs` | `true` | 为防止提示过长,根据上下文窗口使用情况动态截断所有工具输出。如需完整工具输出,设置为 `false` 禁用此功能。 |
|
|
860
|
-
| `
|
|
860
|
+
| `dcp_for_compaction` | `false` | 启用后,当发生 token 限制错误时,DCP(动态上下文剪枝)首先运行,然后立即执行压缩。DCP 清理不必要的上下文后,压缩立即进行。当达到 token 限制时需要更智能的恢复请启用此选项。 |
|
|
861
861
|
|
|
862
862
|
**警告**:这些功能是实验性的,可能会导致意外行为。只有在理解其影响的情况下才启用。
|
|
863
863
|
|
|
@@ -7,3 +7,4 @@
|
|
|
7
7
|
import type { AntigravityProjectContext } from "./types";
|
|
8
8
|
export declare function fetchProjectContext(accessToken: string): Promise<AntigravityProjectContext>;
|
|
9
9
|
export declare function clearProjectContextCache(accessToken?: string): void;
|
|
10
|
+
export declare function invalidateProjectContextByRefreshToken(_refreshToken: string): void;
|
|
@@ -1,25 +1,22 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Antigravity token management utilities.
|
|
3
|
-
* Handles token expiration checking, refresh, and storage format parsing.
|
|
4
|
-
*/
|
|
5
1
|
import type { AntigravityRefreshParts, AntigravityTokenExchangeResult, AntigravityTokens } from "./types";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
export declare class AntigravityTokenRefreshError extends Error {
|
|
3
|
+
code?: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
status: number;
|
|
6
|
+
statusText: string;
|
|
7
|
+
responseBody?: string;
|
|
8
|
+
constructor(options: {
|
|
9
|
+
message: string;
|
|
10
|
+
code?: string;
|
|
11
|
+
description?: string;
|
|
12
|
+
status: number;
|
|
13
|
+
statusText: string;
|
|
14
|
+
responseBody?: string;
|
|
15
|
+
});
|
|
16
|
+
get isInvalidGrant(): boolean;
|
|
17
|
+
get isNetworkError(): boolean;
|
|
18
|
+
}
|
|
13
19
|
export declare function isTokenExpired(tokens: AntigravityTokens): boolean;
|
|
14
|
-
/**
|
|
15
|
-
* Refresh an access token using a refresh token.
|
|
16
|
-
* Exchanges the refresh token for a new access token via Google's OAuth endpoint.
|
|
17
|
-
*
|
|
18
|
-
* @param refreshToken - The refresh token to use
|
|
19
|
-
* @param clientId - Optional custom client ID (defaults to ANTIGRAVITY_CLIENT_ID)
|
|
20
|
-
* @param clientSecret - Optional custom client secret (defaults to ANTIGRAVITY_CLIENT_SECRET)
|
|
21
|
-
* @returns Token exchange result with new access token, or throws on error
|
|
22
|
-
*/
|
|
23
20
|
export declare function refreshAccessToken(refreshToken: string, clientId?: string, clientSecret?: string): Promise<AntigravityTokenExchangeResult>;
|
|
24
21
|
/**
|
|
25
22
|
* Parse a stored token string into its component parts.
|
|
@@ -184,3 +184,22 @@ export interface AntigravityRefreshParts {
|
|
|
184
184
|
projectId?: string;
|
|
185
185
|
managedProjectId?: string;
|
|
186
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* OAuth error payload from Google
|
|
189
|
+
* Google returns errors in multiple formats, this handles all of them
|
|
190
|
+
*/
|
|
191
|
+
export interface OAuthErrorPayload {
|
|
192
|
+
error?: string | {
|
|
193
|
+
status?: string;
|
|
194
|
+
code?: string;
|
|
195
|
+
message?: string;
|
|
196
|
+
};
|
|
197
|
+
error_description?: string;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Parsed OAuth error with normalized fields
|
|
201
|
+
*/
|
|
202
|
+
export interface ParsedOAuthError {
|
|
203
|
+
code?: string;
|
|
204
|
+
description?: string;
|
|
205
|
+
}
|
package/dist/cli/index.js
CHANGED
|
@@ -2244,7 +2244,7 @@ var require_picocolors = __commonJS((exports, module) => {
|
|
|
2244
2244
|
var require_package = __commonJS((exports, module) => {
|
|
2245
2245
|
module.exports = {
|
|
2246
2246
|
name: "oh-my-opencode",
|
|
2247
|
-
version: "2.6.
|
|
2247
|
+
version: "2.6.2",
|
|
2248
2248
|
description: "OpenCode plugin - custom agents (oracle, librarian) and enhanced features",
|
|
2249
2249
|
main: "dist/index.js",
|
|
2250
2250
|
types: "dist/index.d.ts",
|
|
@@ -2297,7 +2297,7 @@ var require_package = __commonJS((exports, module) => {
|
|
|
2297
2297
|
"@ast-grep/cli": "^0.40.0",
|
|
2298
2298
|
"@ast-grep/napi": "^0.40.0",
|
|
2299
2299
|
"@clack/prompts": "^0.11.0",
|
|
2300
|
-
"@code-yeongyu/comment-checker": "^0.6.
|
|
2300
|
+
"@code-yeongyu/comment-checker": "^0.6.1",
|
|
2301
2301
|
"@openauthjs/openauth": "^0.4.3",
|
|
2302
2302
|
"@opencode-ai/plugin": "^1.0.162",
|
|
2303
2303
|
"@opencode-ai/sdk": "^1.0.162",
|
|
@@ -3907,9 +3907,15 @@ function generateOmoConfig(installConfig) {
|
|
|
3907
3907
|
const agents = {};
|
|
3908
3908
|
if (!installConfig.hasClaude) {
|
|
3909
3909
|
agents["Sisyphus"] = { model: "opencode/big-pickle" };
|
|
3910
|
+
}
|
|
3911
|
+
if (installConfig.hasGemini) {
|
|
3912
|
+
agents["librarian"] = { model: "google/gemini-3-flash" };
|
|
3913
|
+
agents["explore"] = { model: "google/gemini-3-flash" };
|
|
3914
|
+
} else if (installConfig.hasClaude && installConfig.isMax20) {
|
|
3915
|
+
agents["explore"] = { model: "anthropic/claude-haiku-4-5" };
|
|
3916
|
+
} else {
|
|
3910
3917
|
agents["librarian"] = { model: "opencode/big-pickle" };
|
|
3911
|
-
|
|
3912
|
-
agents["librarian"] = { model: "opencode/big-pickle" };
|
|
3918
|
+
agents["explore"] = { model: "opencode/big-pickle" };
|
|
3913
3919
|
}
|
|
3914
3920
|
if (!installConfig.hasChatGPT) {
|
|
3915
3921
|
agents["oracle"] = {
|
package/dist/config/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { OhMyOpenCodeConfigSchema, AgentOverrideConfigSchema, AgentOverridesSchema, McpNameSchema, AgentNameSchema, HookNameSchema, SisyphusAgentConfigSchema, ExperimentalConfigSchema, } from "./schema";
|
|
2
|
-
export type { OhMyOpenCodeConfig, AgentOverrideConfig, AgentOverrides, McpName, AgentName, HookName, SisyphusAgentConfig, ExperimentalConfig, DynamicContextPruningConfig, } from "./schema";
|
|
1
|
+
export { OhMyOpenCodeConfigSchema, AgentOverrideConfigSchema, AgentOverridesSchema, McpNameSchema, AgentNameSchema, HookNameSchema, BuiltinCommandNameSchema, SisyphusAgentConfigSchema, ExperimentalConfigSchema, } from "./schema";
|
|
2
|
+
export type { OhMyOpenCodeConfig, AgentOverrideConfig, AgentOverrides, McpName, AgentName, HookName, BuiltinCommandName, SisyphusAgentConfig, ExperimentalConfig, DynamicContextPruningConfig, } from "./schema";
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -54,6 +54,9 @@ export declare const HookNameSchema: z.ZodEnum<{
|
|
|
54
54
|
"empty-message-sanitizer": "empty-message-sanitizer";
|
|
55
55
|
"thinking-block-validator": "thinking-block-validator";
|
|
56
56
|
}>;
|
|
57
|
+
export declare const BuiltinCommandNameSchema: z.ZodEnum<{
|
|
58
|
+
"init-deep": "init-deep";
|
|
59
|
+
}>;
|
|
57
60
|
export declare const AgentOverrideConfigSchema: z.ZodObject<{
|
|
58
61
|
model: z.ZodOptional<z.ZodString>;
|
|
59
62
|
temperature: z.ZodOptional<z.ZodNumber>;
|
|
@@ -635,6 +638,9 @@ export declare const SisyphusAgentConfigSchema: z.ZodObject<{
|
|
|
635
638
|
planner_enabled: z.ZodOptional<z.ZodBoolean>;
|
|
636
639
|
replace_plan: z.ZodOptional<z.ZodBoolean>;
|
|
637
640
|
}, z.core.$strip>;
|
|
641
|
+
export declare const CommentCheckerConfigSchema: z.ZodObject<{
|
|
642
|
+
custom_prompt: z.ZodOptional<z.ZodString>;
|
|
643
|
+
}, z.core.$strip>;
|
|
638
644
|
export declare const DynamicContextPruningConfigSchema: z.ZodObject<{
|
|
639
645
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
640
646
|
notification: z.ZodDefault<z.ZodEnum<{
|
|
@@ -693,7 +699,7 @@ export declare const ExperimentalConfigSchema: z.ZodObject<{
|
|
|
693
699
|
}, z.core.$strip>>;
|
|
694
700
|
}, z.core.$strip>>;
|
|
695
701
|
}, z.core.$strip>>;
|
|
696
|
-
|
|
702
|
+
dcp_for_compaction: z.ZodOptional<z.ZodBoolean>;
|
|
697
703
|
}, z.core.$strip>;
|
|
698
704
|
export declare const OhMyOpenCodeConfigSchema: z.ZodObject<{
|
|
699
705
|
$schema: z.ZodOptional<z.ZodString>;
|
|
@@ -735,6 +741,9 @@ export declare const OhMyOpenCodeConfigSchema: z.ZodObject<{
|
|
|
735
741
|
"empty-message-sanitizer": "empty-message-sanitizer";
|
|
736
742
|
"thinking-block-validator": "thinking-block-validator";
|
|
737
743
|
}>>>;
|
|
744
|
+
disabled_commands: z.ZodOptional<z.ZodArray<z.ZodEnum<{
|
|
745
|
+
"init-deep": "init-deep";
|
|
746
|
+
}>>>;
|
|
738
747
|
agents: z.ZodOptional<z.ZodObject<{
|
|
739
748
|
build: z.ZodOptional<z.ZodObject<{
|
|
740
749
|
model: z.ZodOptional<z.ZodString>;
|
|
@@ -1270,6 +1279,9 @@ export declare const OhMyOpenCodeConfigSchema: z.ZodObject<{
|
|
|
1270
1279
|
planner_enabled: z.ZodOptional<z.ZodBoolean>;
|
|
1271
1280
|
replace_plan: z.ZodOptional<z.ZodBoolean>;
|
|
1272
1281
|
}, z.core.$strip>>;
|
|
1282
|
+
comment_checker: z.ZodOptional<z.ZodObject<{
|
|
1283
|
+
custom_prompt: z.ZodOptional<z.ZodString>;
|
|
1284
|
+
}, z.core.$strip>>;
|
|
1273
1285
|
experimental: z.ZodOptional<z.ZodObject<{
|
|
1274
1286
|
aggressive_truncation: z.ZodOptional<z.ZodBoolean>;
|
|
1275
1287
|
auto_resume: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -1302,7 +1314,7 @@ export declare const OhMyOpenCodeConfigSchema: z.ZodObject<{
|
|
|
1302
1314
|
}, z.core.$strip>>;
|
|
1303
1315
|
}, z.core.$strip>>;
|
|
1304
1316
|
}, z.core.$strip>>;
|
|
1305
|
-
|
|
1317
|
+
dcp_for_compaction: z.ZodOptional<z.ZodBoolean>;
|
|
1306
1318
|
}, z.core.$strip>>;
|
|
1307
1319
|
auto_update: z.ZodOptional<z.ZodBoolean>;
|
|
1308
1320
|
}, z.core.$strip>;
|
|
@@ -1311,7 +1323,9 @@ export type AgentOverrideConfig = z.infer<typeof AgentOverrideConfigSchema>;
|
|
|
1311
1323
|
export type AgentOverrides = z.infer<typeof AgentOverridesSchema>;
|
|
1312
1324
|
export type AgentName = z.infer<typeof AgentNameSchema>;
|
|
1313
1325
|
export type HookName = z.infer<typeof HookNameSchema>;
|
|
1326
|
+
export type BuiltinCommandName = z.infer<typeof BuiltinCommandNameSchema>;
|
|
1314
1327
|
export type SisyphusAgentConfig = z.infer<typeof SisyphusAgentConfigSchema>;
|
|
1328
|
+
export type CommentCheckerConfig = z.infer<typeof CommentCheckerConfigSchema>;
|
|
1315
1329
|
export type ExperimentalConfig = z.infer<typeof ExperimentalConfigSchema>;
|
|
1316
1330
|
export type DynamicContextPruningConfig = z.infer<typeof DynamicContextPruningConfigSchema>;
|
|
1317
1331
|
export { McpNameSchema, type McpName } from "../mcp/types";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const INIT_DEEP_TEMPLATE = "# Initialize Deep Knowledge Base\n\nGenerate comprehensive AGENTS.md files across project hierarchy. Combines root-level project knowledge (gen-knowledge) with complexity-based subdirectory documentation (gen-knowledge-deep).\n\n## Usage\n\n```\n/init-deep # Analyze and generate hierarchical AGENTS.md\n/init-deep --create-new # Force create from scratch (ignore existing)\n/init-deep --max-depth=2 # Limit to N directory levels (default: 3)\n```\n\n---\n\n## Core Principles\n\n- **Telegraphic Style**: Sacrifice grammar for concision (\"Project uses React\" \u2192 \"React 18\")\n- **Predict-then-Compare**: Predict standard \u2192 find actual \u2192 document ONLY deviations\n- **Hierarchy Aware**: Parent covers general, children cover specific\n- **No Redundancy**: Child AGENTS.md NEVER repeats parent content\n\n---\n\n## Process\n\n<critical>\n**MANDATORY: TodoWrite for ALL phases. Mark in_progress \u2192 completed in real-time.**\n</critical>\n\n### Phase 0: Initialize\n\n```\nTodoWrite([\n { id: \"p1-analysis\", content: \"Parallel project structure & complexity analysis\", status: \"pending\", priority: \"high\" },\n { id: \"p2-scoring\", content: \"Score directories, determine AGENTS.md locations\", status: \"pending\", priority: \"high\" },\n { id: \"p3-root\", content: \"Generate root AGENTS.md with Predict-then-Compare\", status: \"pending\", priority: \"high\" },\n { id: \"p4-subdirs\", content: \"Generate subdirectory AGENTS.md files in parallel\", status: \"pending\", priority: \"high\" },\n { id: \"p5-review\", content: \"Review, deduplicate, validate all files\", status: \"pending\", priority: \"medium\" }\n])\n```\n\n---\n\n## Phase 1: Parallel Project Analysis\n\n**Mark \"p1-analysis\" as in_progress.**\n\nLaunch **ALL tasks simultaneously**:\n\n<parallel-tasks>\n\n### Structural Analysis (bash - run in parallel)\n```bash\n# Task A: Directory depth analysis\nfind . -type d -not -path '*/\\.*' -not -path '*/node_modules/*' -not -path '*/venv/*' -not -path '*/__pycache__/*' -not -path '*/dist/*' -not -path '*/build/*' | awk -F/ '{print NF-1}' | sort -n | uniq -c\n\n# Task B: File count per directory \nfind . -type f -not -path '*/\\.*' -not -path '*/node_modules/*' -not -path '*/venv/*' -not -path '*/__pycache__/*' | sed 's|/[^/]*$||' | sort | uniq -c | sort -rn | head -30\n\n# Task C: Code concentration\nfind . -type f \\( -name \"*.py\" -o -name \"*.ts\" -o -name \"*.tsx\" -o -name \"*.js\" -o -name \"*.jsx\" -o -name \"*.go\" -o -name \"*.rs\" -o -name \"*.java\" \\) -not -path '*/node_modules/*' -not -path '*/venv/*' | sed 's|/[^/]*$||' | sort | uniq -c | sort -rn | head -20\n\n# Task D: Existing knowledge files\nfind . -type f \\( -name \"AGENTS.md\" -o -name \"CLAUDE.md\" \\) -not -path '*/node_modules/*' 2>/dev/null\n```\n\n### Context Gathering (Explore agents - background_task in parallel)\n\n```\nbackground_task(agent=\"explore\", prompt=\"Project structure: PREDICT standard {lang} patterns \u2192 FIND package.json/pyproject.toml/go.mod \u2192 REPORT deviations only\")\n\nbackground_task(agent=\"explore\", prompt=\"Entry points: PREDICT typical (main.py, index.ts) \u2192 FIND actual \u2192 REPORT non-standard organization\")\n\nbackground_task(agent=\"explore\", prompt=\"Conventions: FIND .cursor/rules, .cursorrules, eslintrc, pyproject.toml \u2192 REPORT project-specific rules DIFFERENT from defaults\")\n\nbackground_task(agent=\"explore\", prompt=\"Anti-patterns: FIND comments with 'DO NOT', 'NEVER', 'ALWAYS', 'LEGACY', 'DEPRECATED' \u2192 REPORT forbidden patterns\")\n\nbackground_task(agent=\"explore\", prompt=\"Build/CI: FIND .github/workflows, Makefile, justfile \u2192 REPORT non-standard build/deploy patterns\")\n\nbackground_task(agent=\"explore\", prompt=\"Test patterns: FIND pytest.ini, jest.config, test structure \u2192 REPORT unique testing conventions\")\n```\n\n</parallel-tasks>\n\n**Collect all results. Mark \"p1-analysis\" as completed.**\n\n---\n\n## Phase 2: Complexity Scoring & Location Decision\n\n**Mark \"p2-scoring\" as in_progress.**\n\n### Scoring Matrix\n\n| Factor | Weight | Threshold |\n|--------|--------|-----------|\n| File count | 3x | >20 files = high |\n| Subdirectory count | 2x | >5 subdirs = high |\n| Code file ratio | 2x | >70% code = high |\n| Unique patterns | 1x | Has own config |\n| Module boundary | 2x | Has __init__.py/index.ts |\n\n### Decision Rules\n\n| Score | Action |\n|-------|--------|\n| **Root (.)** | ALWAYS create AGENTS.md |\n| **High (>15)** | Create dedicated AGENTS.md |\n| **Medium (8-15)** | Create if distinct domain |\n| **Low (<8)** | Skip, parent sufficient |\n\n### Output Format\n\n```\nAGENTS_LOCATIONS = [\n { path: \".\", type: \"root\" },\n { path: \"src/api\", score: 18, reason: \"high complexity, 45 files\" },\n { path: \"src/hooks\", score: 12, reason: \"distinct domain, unique patterns\" },\n]\n```\n\n**Mark \"p2-scoring\" as completed.**\n\n---\n\n## Phase 3: Generate Root AGENTS.md\n\n**Mark \"p3-root\" as in_progress.**\n\nRoot AGENTS.md gets **full treatment** with Predict-then-Compare synthesis.\n\n### Required Sections\n\n```markdown\n# PROJECT KNOWLEDGE BASE\n\n**Generated:** {TIMESTAMP}\n**Commit:** {SHORT_SHA}\n**Branch:** {BRANCH}\n\n## OVERVIEW\n\n{1-2 sentences: what project does, core tech stack}\n\n## STRUCTURE\n\n\\`\\`\\`\n{project-root}/\n\u251C\u2500\u2500 {dir}/ # {non-obvious purpose only}\n\u2514\u2500\u2500 {entry} # entry point\n\\`\\`\\`\n\n## WHERE TO LOOK\n\n| Task | Location | Notes |\n|------|----------|-------|\n| Add feature X | \\`src/x/\\` | {pattern hint} |\n\n## CONVENTIONS\n\n{ONLY deviations from standard - skip generic advice}\n\n- **{rule}**: {specific detail}\n\n## ANTI-PATTERNS (THIS PROJECT)\n\n{Things explicitly forbidden HERE}\n\n- **{pattern}**: {why} \u2192 {alternative}\n\n## UNIQUE STYLES\n\n{Project-specific coding styles}\n\n- **{style}**: {how different}\n\n## COMMANDS\n\n\\`\\`\\`bash\n{dev-command}\n{test-command}\n{build-command}\n\\`\\`\\`\n\n## NOTES\n\n{Gotchas, non-obvious info}\n```\n\n### Quality Gates\n\n- [ ] Size: 50-150 lines\n- [ ] No generic advice (\"write clean code\")\n- [ ] No obvious info (\"tests/ has tests\")\n- [ ] Every item is project-specific\n\n**Mark \"p3-root\" as completed.**\n\n---\n\n## Phase 4: Generate Subdirectory AGENTS.md\n\n**Mark \"p4-subdirs\" as in_progress.**\n\nFor each location in AGENTS_LOCATIONS (except root), launch **parallel document-writer agents**:\n\n```typescript\nfor (const loc of AGENTS_LOCATIONS.filter(l => l.path !== \".\")) {\n background_task({\n agent: \"document-writer\",\n prompt: \\`\n Generate AGENTS.md for: ${loc.path}\n \n CONTEXT:\n - Complexity reason: ${loc.reason}\n - Parent AGENTS.md: ./AGENTS.md (already covers project overview)\n \n CRITICAL RULES:\n 1. Focus ONLY on this directory's specific context\n 2. NEVER repeat parent AGENTS.md content\n 3. Shorter is better - 30-80 lines max\n 4. Telegraphic style - sacrifice grammar\n \n REQUIRED SECTIONS:\n - OVERVIEW (1 line: what this directory does)\n - STRUCTURE (only if >5 subdirs)\n - WHERE TO LOOK (directory-specific tasks)\n - CONVENTIONS (only if DIFFERENT from root)\n - ANTI-PATTERNS (directory-specific only)\n \n OUTPUT: Write to ${loc.path}/AGENTS.md\n \\`\n })\n}\n```\n\n**Wait for all agents. Mark \"p4-subdirs\" as completed.**\n\n---\n\n## Phase 5: Review & Deduplicate\n\n**Mark \"p5-review\" as in_progress.**\n\n### Validation Checklist\n\nFor EACH generated AGENTS.md:\n\n| Check | Action if Fail |\n|-------|----------------|\n| Contains generic advice | REMOVE the line |\n| Repeats parent content | REMOVE the line |\n| Missing required section | ADD it |\n| Over 150 lines (root) / 80 lines (subdir) | TRIM |\n| Verbose explanations | REWRITE telegraphic |\n\n### Cross-Reference Validation\n\n```\nFor each child AGENTS.md:\n For each line in child:\n If similar line exists in parent:\n REMOVE from child (parent already covers)\n```\n\n**Mark \"p5-review\" as completed.**\n\n---\n\n## Final Report\n\n```\n=== init-deep Complete ===\n\nFiles Generated:\n \u2713 ./AGENTS.md (root, {N} lines)\n \u2713 ./src/hooks/AGENTS.md ({N} lines)\n \u2713 ./src/tools/AGENTS.md ({N} lines)\n\nDirectories Analyzed: {N}\nAGENTS.md Created: {N}\nTotal Lines: {N}\n\nHierarchy:\n ./AGENTS.md\n \u251C\u2500\u2500 src/hooks/AGENTS.md\n \u2514\u2500\u2500 src/tools/AGENTS.md\n```\n\n---\n\n## Anti-Patterns for THIS Command\n\n- **Over-documenting**: Not every directory needs AGENTS.md\n- **Redundancy**: Child must NOT repeat parent\n- **Generic content**: Remove anything that applies to ALL projects\n- **Sequential execution**: MUST use parallel agents\n- **Deep nesting**: Rarely need AGENTS.md at depth 4+\n- **Verbose style**: \"This directory contains...\" \u2192 just list it";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { CommandDefinition } from "../claude-code-command-loader";
|
|
2
|
+
export type BuiltinCommandName = "init-deep";
|
|
3
|
+
export interface BuiltinCommandConfig {
|
|
4
|
+
disabled_commands?: BuiltinCommandName[];
|
|
5
|
+
}
|
|
6
|
+
export type BuiltinCommands = Record<string, CommandDefinition>;
|
package/dist/google-auth.js
CHANGED
|
@@ -290,10 +290,66 @@ function startCallbackServer(timeoutMs = 5 * 60 * 1000) {
|
|
|
290
290
|
};
|
|
291
291
|
}
|
|
292
292
|
// src/auth/antigravity/token.ts
|
|
293
|
+
class AntigravityTokenRefreshError extends Error {
|
|
294
|
+
code;
|
|
295
|
+
description;
|
|
296
|
+
status;
|
|
297
|
+
statusText;
|
|
298
|
+
responseBody;
|
|
299
|
+
constructor(options) {
|
|
300
|
+
super(options.message);
|
|
301
|
+
this.name = "AntigravityTokenRefreshError";
|
|
302
|
+
this.code = options.code;
|
|
303
|
+
this.description = options.description;
|
|
304
|
+
this.status = options.status;
|
|
305
|
+
this.statusText = options.statusText;
|
|
306
|
+
this.responseBody = options.responseBody;
|
|
307
|
+
}
|
|
308
|
+
get isInvalidGrant() {
|
|
309
|
+
return this.code === "invalid_grant";
|
|
310
|
+
}
|
|
311
|
+
get isNetworkError() {
|
|
312
|
+
return this.status === 0;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function parseOAuthErrorPayload(text) {
|
|
316
|
+
if (!text) {
|
|
317
|
+
return {};
|
|
318
|
+
}
|
|
319
|
+
try {
|
|
320
|
+
const payload = JSON.parse(text);
|
|
321
|
+
let code;
|
|
322
|
+
if (typeof payload.error === "string") {
|
|
323
|
+
code = payload.error;
|
|
324
|
+
} else if (payload.error && typeof payload.error === "object") {
|
|
325
|
+
code = payload.error.status ?? payload.error.code;
|
|
326
|
+
}
|
|
327
|
+
return {
|
|
328
|
+
code,
|
|
329
|
+
description: payload.error_description
|
|
330
|
+
};
|
|
331
|
+
} catch {
|
|
332
|
+
return { description: text };
|
|
333
|
+
}
|
|
334
|
+
}
|
|
293
335
|
function isTokenExpired(tokens) {
|
|
294
336
|
const expirationTime = tokens.timestamp + tokens.expires_in * 1000;
|
|
295
337
|
return Date.now() >= expirationTime - ANTIGRAVITY_TOKEN_REFRESH_BUFFER_MS;
|
|
296
338
|
}
|
|
339
|
+
var MAX_REFRESH_RETRIES = 3;
|
|
340
|
+
var INITIAL_RETRY_DELAY_MS = 1000;
|
|
341
|
+
function calculateRetryDelay(attempt) {
|
|
342
|
+
return Math.min(INITIAL_RETRY_DELAY_MS * Math.pow(2, attempt), 1e4);
|
|
343
|
+
}
|
|
344
|
+
function isRetryableError(status) {
|
|
345
|
+
if (status === 0)
|
|
346
|
+
return true;
|
|
347
|
+
if (status === 429)
|
|
348
|
+
return true;
|
|
349
|
+
if (status >= 500 && status < 600)
|
|
350
|
+
return true;
|
|
351
|
+
return false;
|
|
352
|
+
}
|
|
297
353
|
async function refreshAccessToken(refreshToken, clientId = ANTIGRAVITY_CLIENT_ID, clientSecret = ANTIGRAVITY_CLIENT_SECRET) {
|
|
298
354
|
const params = new URLSearchParams({
|
|
299
355
|
grant_type: "refresh_token",
|
|
@@ -301,24 +357,67 @@ async function refreshAccessToken(refreshToken, clientId = ANTIGRAVITY_CLIENT_ID
|
|
|
301
357
|
client_id: clientId,
|
|
302
358
|
client_secret: clientSecret
|
|
303
359
|
});
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
360
|
+
let lastError;
|
|
361
|
+
for (let attempt = 0;attempt <= MAX_REFRESH_RETRIES; attempt++) {
|
|
362
|
+
try {
|
|
363
|
+
const response = await fetch(GOOGLE_TOKEN_URL, {
|
|
364
|
+
method: "POST",
|
|
365
|
+
headers: {
|
|
366
|
+
"Content-Type": "application/x-www-form-urlencoded"
|
|
367
|
+
},
|
|
368
|
+
body: params
|
|
369
|
+
});
|
|
370
|
+
if (response.ok) {
|
|
371
|
+
const data = await response.json();
|
|
372
|
+
return {
|
|
373
|
+
access_token: data.access_token,
|
|
374
|
+
refresh_token: data.refresh_token || refreshToken,
|
|
375
|
+
expires_in: data.expires_in,
|
|
376
|
+
token_type: data.token_type
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
const responseBody = await response.text().catch(() => {
|
|
380
|
+
return;
|
|
381
|
+
});
|
|
382
|
+
const parsed = parseOAuthErrorPayload(responseBody);
|
|
383
|
+
lastError = new AntigravityTokenRefreshError({
|
|
384
|
+
message: parsed.description || `Token refresh failed: ${response.status} ${response.statusText}`,
|
|
385
|
+
code: parsed.code,
|
|
386
|
+
description: parsed.description,
|
|
387
|
+
status: response.status,
|
|
388
|
+
statusText: response.statusText,
|
|
389
|
+
responseBody
|
|
390
|
+
});
|
|
391
|
+
if (parsed.code === "invalid_grant") {
|
|
392
|
+
throw lastError;
|
|
393
|
+
}
|
|
394
|
+
if (!isRetryableError(response.status)) {
|
|
395
|
+
throw lastError;
|
|
396
|
+
}
|
|
397
|
+
if (attempt < MAX_REFRESH_RETRIES) {
|
|
398
|
+
const delay = calculateRetryDelay(attempt);
|
|
399
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
400
|
+
}
|
|
401
|
+
} catch (error) {
|
|
402
|
+
if (error instanceof AntigravityTokenRefreshError) {
|
|
403
|
+
throw error;
|
|
404
|
+
}
|
|
405
|
+
lastError = new AntigravityTokenRefreshError({
|
|
406
|
+
message: error instanceof Error ? error.message : "Network error during token refresh",
|
|
407
|
+
status: 0,
|
|
408
|
+
statusText: "Network Error"
|
|
409
|
+
});
|
|
410
|
+
if (attempt < MAX_REFRESH_RETRIES) {
|
|
411
|
+
const delay = calculateRetryDelay(attempt);
|
|
412
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
413
|
+
}
|
|
414
|
+
}
|
|
314
415
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
token_type: data.token_type
|
|
321
|
-
};
|
|
416
|
+
throw lastError || new AntigravityTokenRefreshError({
|
|
417
|
+
message: "Token refresh failed after all retries",
|
|
418
|
+
status: 0,
|
|
419
|
+
statusText: "Max Retries Exceeded"
|
|
420
|
+
});
|
|
322
421
|
}
|
|
323
422
|
function parseStoredToken(stored) {
|
|
324
423
|
const parts = stored.split("|");
|
|
@@ -543,6 +642,10 @@ function clearProjectContextCache(accessToken) {
|
|
|
543
642
|
projectContextCache.clear();
|
|
544
643
|
}
|
|
545
644
|
}
|
|
645
|
+
function invalidateProjectContextByRefreshToken(_refreshToken) {
|
|
646
|
+
projectContextCache.clear();
|
|
647
|
+
debugLog(`[invalidateProjectContextByRefreshToken] Cleared all project context cache due to refresh token invalidation`);
|
|
648
|
+
}
|
|
546
649
|
// src/auth/antigravity/request.ts
|
|
547
650
|
function buildRequestHeaders(accessToken) {
|
|
548
651
|
return {
|
|
@@ -1257,7 +1360,7 @@ function debugLog4(message) {
|
|
|
1257
1360
|
console.log(`[antigravity-fetch] ${message}`);
|
|
1258
1361
|
}
|
|
1259
1362
|
}
|
|
1260
|
-
function
|
|
1363
|
+
function isRetryableError2(status) {
|
|
1261
1364
|
if (status === 0)
|
|
1262
1365
|
return true;
|
|
1263
1366
|
if (status === 429)
|
|
@@ -1275,11 +1378,11 @@ var GCP_PERMISSION_ERROR_PATTERNS = [
|
|
|
1275
1378
|
function isGcpPermissionError(text) {
|
|
1276
1379
|
return GCP_PERMISSION_ERROR_PATTERNS.some((pattern) => text.includes(pattern));
|
|
1277
1380
|
}
|
|
1278
|
-
function
|
|
1381
|
+
function calculateRetryDelay2(attempt) {
|
|
1279
1382
|
return Math.min(200 * Math.pow(2, attempt), 2000);
|
|
1280
1383
|
}
|
|
1281
1384
|
async function isRetryableResponse(response) {
|
|
1282
|
-
if (
|
|
1385
|
+
if (isRetryableError2(response.status))
|
|
1283
1386
|
return true;
|
|
1284
1387
|
if (response.status === 403) {
|
|
1285
1388
|
try {
|
|
@@ -1358,7 +1461,7 @@ async function attemptFetch(options) {
|
|
|
1358
1461
|
const text = await response.clone().text();
|
|
1359
1462
|
if (isGcpPermissionError(text)) {
|
|
1360
1463
|
if (attempt < maxPermissionRetries) {
|
|
1361
|
-
const delay =
|
|
1464
|
+
const delay = calculateRetryDelay2(attempt);
|
|
1362
1465
|
debugLog4(`[RETRY] GCP permission error, retry ${attempt + 1}/${maxPermissionRetries} after ${delay}ms`);
|
|
1363
1466
|
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
1364
1467
|
continue;
|
|
@@ -1479,6 +1582,14 @@ function createAntigravityFetch(getAuth, client, providerId, clientId, clientSec
|
|
|
1479
1582
|
});
|
|
1480
1583
|
debugLog4("Token refreshed successfully");
|
|
1481
1584
|
} catch (error) {
|
|
1585
|
+
if (error instanceof AntigravityTokenRefreshError) {
|
|
1586
|
+
if (error.isInvalidGrant) {
|
|
1587
|
+
debugLog4(`[REFRESH] Token revoked (invalid_grant), clearing caches`);
|
|
1588
|
+
invalidateProjectContextByRefreshToken(refreshParts.refreshToken);
|
|
1589
|
+
clearProjectContextCache();
|
|
1590
|
+
}
|
|
1591
|
+
throw new Error(`Antigravity: Token refresh failed: ${error.description || error.message}${error.code ? ` (${error.code})` : ""}`);
|
|
1592
|
+
}
|
|
1482
1593
|
throw new Error(`Antigravity: Token refresh failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
1483
1594
|
}
|
|
1484
1595
|
}
|
|
@@ -1560,10 +1671,29 @@ function createAntigravityFetch(getAuth, client, providerId, clientId, clientSec
|
|
|
1560
1671
|
debugLog4("[401] Token refreshed, retrying request...");
|
|
1561
1672
|
return executeWithEndpoints();
|
|
1562
1673
|
} catch (refreshError) {
|
|
1674
|
+
if (refreshError instanceof AntigravityTokenRefreshError) {
|
|
1675
|
+
if (refreshError.isInvalidGrant) {
|
|
1676
|
+
debugLog4(`[401] Token revoked (invalid_grant), clearing caches`);
|
|
1677
|
+
invalidateProjectContextByRefreshToken(refreshParts.refreshToken);
|
|
1678
|
+
clearProjectContextCache();
|
|
1679
|
+
}
|
|
1680
|
+
debugLog4(`[401] Token refresh failed: ${refreshError.description || refreshError.message}`);
|
|
1681
|
+
return new Response(JSON.stringify({
|
|
1682
|
+
error: {
|
|
1683
|
+
message: refreshError.description || refreshError.message,
|
|
1684
|
+
type: refreshError.isInvalidGrant ? "token_revoked" : "unauthorized",
|
|
1685
|
+
code: refreshError.code || "token_refresh_failed"
|
|
1686
|
+
}
|
|
1687
|
+
}), {
|
|
1688
|
+
status: 401,
|
|
1689
|
+
statusText: "Unauthorized",
|
|
1690
|
+
headers: { "Content-Type": "application/json" }
|
|
1691
|
+
});
|
|
1692
|
+
}
|
|
1563
1693
|
debugLog4(`[401] Token refresh failed: ${refreshError instanceof Error ? refreshError.message : "Unknown error"}`);
|
|
1564
1694
|
return new Response(JSON.stringify({
|
|
1565
1695
|
error: {
|
|
1566
|
-
message:
|
|
1696
|
+
message: refreshError instanceof Error ? refreshError.message : "Unknown error",
|
|
1567
1697
|
type: "unauthorized",
|
|
1568
1698
|
code: "token_refresh_failed"
|
|
1569
1699
|
}
|
|
@@ -40,8 +40,9 @@ export interface CheckResult {
|
|
|
40
40
|
* Run comment-checker CLI with given input.
|
|
41
41
|
* @param input Hook input to check
|
|
42
42
|
* @param cliPath Optional explicit path to CLI binary
|
|
43
|
+
* @param customPrompt Optional custom prompt to replace default warning message
|
|
43
44
|
*/
|
|
44
|
-
export declare function runCommentChecker(input: HookInput, cliPath?: string): Promise<CheckResult>;
|
|
45
|
+
export declare function runCommentChecker(input: HookInput, cliPath?: string, customPrompt?: string): Promise<CheckResult>;
|
|
45
46
|
/**
|
|
46
47
|
* Check if CLI is available (sync check, no download).
|
|
47
48
|
*/
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import type { CommentCheckerConfig } from "../../config/schema";
|
|
2
|
+
export declare function createCommentCheckerHooks(config?: CommentCheckerConfig): {
|
|
2
3
|
"tool.execute.before": (input: {
|
|
3
4
|
tool: string;
|
|
4
5
|
sessionID: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Plugin } from "@opencode-ai/plugin";
|
|
2
2
|
declare const OhMyOpenCodePlugin: Plugin;
|
|
3
3
|
export default OhMyOpenCodePlugin;
|
|
4
|
-
export type { OhMyOpenCodeConfig, AgentName, AgentOverrideConfig, AgentOverrides, McpName, HookName, } from "./config";
|
|
4
|
+
export type { OhMyOpenCodeConfig, AgentName, AgentOverrideConfig, AgentOverrides, McpName, HookName, BuiltinCommandName, } from "./config";
|
|
5
5
|
export type { ConfigLoadError } from "./shared/config-errors";
|