@gajae-code/ai 0.16.7 → 0.17.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.
- package/CHANGELOG.md +44 -1
- package/dist/types/auth-storage.d.ts +23 -4
- package/dist/types/models.d.ts +14 -0
- package/dist/types/provider-models/special.d.ts +12 -0
- package/dist/types/providers/anthropic.d.ts +1 -1
- package/dist/types/providers/cursor.d.ts +33 -21
- package/dist/types/providers/devin-acp.d.ts +157 -0
- package/dist/types/providers/google-gemini-headers.d.ts +1 -1
- package/dist/types/providers/mock.d.ts +2 -0
- package/dist/types/providers/openai-responses-shared.d.ts +21 -1
- package/dist/types/providers/register-builtins.d.ts +1 -0
- package/dist/types/types.d.ts +52 -11
- package/dist/types/utils/block-symbols.d.ts +15 -5
- package/dist/types/utils/fallback-transport.d.ts +4 -1
- package/dist/types/utils.d.ts +13 -0
- package/package.json +4 -3
- package/src/api-registry.ts +1 -0
- package/src/auth-broker/redact.ts +10 -2
- package/src/auth-gateway/server.ts +56 -3
- package/src/auth-storage.ts +330 -116
- package/src/model-manager.ts +21 -2
- package/src/models.d.ts +14 -0
- package/src/models.json +117 -0
- package/src/models.ts +18 -0
- package/src/provider-models/descriptors.ts +7 -0
- package/src/provider-models/openai-compat.ts +14 -0
- package/src/provider-models/special.ts +39 -0
- package/src/providers/anthropic.d.ts +1 -1
- package/src/providers/anthropic.ts +1 -1
- package/src/providers/azure-openai-responses.ts +10 -1
- package/src/providers/cursor.d.ts +33 -21
- package/src/providers/cursor.ts +2024 -508
- package/src/providers/devin-acp.d.ts +157 -0
- package/src/providers/devin-acp.ts +1103 -0
- package/src/providers/google-gemini-headers.d.ts +1 -1
- package/src/providers/google-gemini-headers.ts +1 -1
- package/src/providers/mock.ts +16 -1
- package/src/providers/openai-chat-server.ts +3 -3
- package/src/providers/openai-codex-responses.ts +27 -17
- package/src/providers/openai-responses-server.ts +5 -5
- package/src/providers/openai-responses-shared.d.ts +21 -1
- package/src/providers/openai-responses-shared.ts +60 -6
- package/src/providers/openai-responses.ts +10 -1
- package/src/providers/register-builtins.d.ts +1 -0
- package/src/providers/register-builtins.ts +21 -1
- package/src/stream.ts +14 -0
- package/src/types.d.ts +52 -11
- package/src/types.ts +70 -8
- package/src/utils/block-symbols.d.ts +15 -5
- package/src/utils/block-symbols.ts +16 -6
- package/src/utils/discovery/cursor.ts +3 -2
- package/src/utils/fallback-transport.d.ts +4 -1
- package/src/utils/fallback-transport.ts +12 -5
- package/src/utils.d.ts +13 -0
- package/src/utils.ts +17 -0
- package/dist/types/utils/codex-entitlement.d.ts +0 -22
- package/src/utils/codex-entitlement.d.ts +0 -22
- package/src/utils/codex-entitlement.ts +0 -57
package/src/types.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { AnthropicOptions } from "./providers/anthropic";
|
|
|
4
4
|
import type { AzureOpenAIResponsesOptions } from "./providers/azure-openai-responses";
|
|
5
5
|
import type { CursorOptions } from "./providers/cursor";
|
|
6
6
|
import type { DeleteArgs, DeleteResult, DiagnosticsArgs, DiagnosticsResult, GrepArgs, GrepResult, LsArgs, LsResult, McpResult, PiBashExecArgs, PiBashExecResult, PiEditExecArgs, PiEditExecResult, PiFindExecArgs, PiFindExecResult, PiGrepExecArgs, PiGrepExecResult, PiLsExecArgs, PiLsExecResult, PiReadExecArgs, PiReadExecResult, PiWriteExecArgs, PiWriteExecResult, ReadArgs, ReadResult, ShellArgs, ShellResult, WriteArgs, WriteResult } from "./providers/cursor/gen/agent_pb";
|
|
7
|
+
import type { DevinAcpConfig, DevinAcpOptions } from "./providers/devin-acp";
|
|
7
8
|
import type { GoogleOptions } from "./providers/google";
|
|
8
9
|
import type { GoogleGeminiCliOptions } from "./providers/google-gemini-cli";
|
|
9
10
|
import type { GoogleVertexOptions } from "./providers/google-vertex";
|
|
@@ -16,7 +17,7 @@ import type { AssistantMessageEventStream } from "./utils/event-stream";
|
|
|
16
17
|
import type { FallbackAttemptToken, TransportFailureFacts } from "./utils/fallback-transport";
|
|
17
18
|
import type { UnicodeEscapeEvidence } from "./utils/json-parse";
|
|
18
19
|
export type { AssistantMessageEventStream } from "./utils/event-stream";
|
|
19
|
-
export type KnownApi = "openai-completions" | "openai-responses" | "openai-codex-responses" | "azure-openai-responses" | "anthropic-messages" | "bedrock-converse-stream" | "google-generative-ai" | "google-gemini-cli" | "google-vertex" | "ollama-chat" | "cursor-agent" | "kiro-codewhisperer-stream";
|
|
20
|
+
export type KnownApi = "openai-completions" | "openai-responses" | "openai-codex-responses" | "azure-openai-responses" | "anthropic-messages" | "bedrock-converse-stream" | "google-generative-ai" | "google-gemini-cli" | "google-vertex" | "ollama-chat" | "cursor-agent" | "devin-acp" | "kiro-codewhisperer-stream";
|
|
20
21
|
export type Api = KnownApi | (string & {});
|
|
21
22
|
export interface ApiOptionsMap {
|
|
22
23
|
"anthropic-messages": AnthropicOptions;
|
|
@@ -30,6 +31,7 @@ export interface ApiOptionsMap {
|
|
|
30
31
|
"google-vertex": GoogleVertexOptions;
|
|
31
32
|
"ollama-chat": OllamaChatOptions;
|
|
32
33
|
"cursor-agent": CursorOptions;
|
|
34
|
+
"devin-acp": DevinAcpOptions;
|
|
33
35
|
"kiro-codewhisperer-stream": KiroCodeWhispererOptions;
|
|
34
36
|
}
|
|
35
37
|
export type OptionsForApi<TApi extends Api> = StreamOptions | (TApi extends keyof ApiOptionsMap ? ApiOptionsMap[TApi] : never);
|
|
@@ -54,7 +56,7 @@ export interface ThinkingConfig {
|
|
|
54
56
|
/** Provider-specific transport used to encode the selected effort. */
|
|
55
57
|
mode: ThinkingControlMode;
|
|
56
58
|
}
|
|
57
|
-
export declare const KNOWN_PROVIDERS: readonly ["alibaba-token-plan", "amazon-bedrock", "kiro", "azure-openai", "anthropic", "google", "google-gemini-cli", "google-antigravity", "google-vertex", "openai", "openai-codex", "opencodex", "kimi-code", "minimax-code", "minimax-code-cn", "github-copilot", "fireworks", "firepass", "fugu", "gitlab-duo", "cursor", "jetbrains-junie", "deepseek", "deepinfra", "xai", "groq", "cerebras", "openrouter", "kilo", "vercel-ai-gateway", "zai", "glm-zcode", "mistral", "minimax", "opencode-go", "commandcode-goat", "opencode-zen", "opengateway", "bizrouter", "mara", "synthetic", "cloudflare-ai-gateway", "huggingface", "litellm", "moonshot", "nvidia", "nanogpt", "ollama", "ollama-cloud", "qianfan", "qwen-portal", "sglang", "together", "venice", "vllm", "xiaomi", "xiaomi-token-plan-sgp", "xiaomi-token-plan-ams", "xiaomi-token-plan-cn", "zenmux", "lm-studio", "omlx"];
|
|
59
|
+
export declare const KNOWN_PROVIDERS: readonly ["alibaba-token-plan", "amazon-bedrock", "kiro", "azure-openai", "anthropic", "google", "google-gemini-cli", "google-antigravity", "google-vertex", "openai", "openai-codex", "opencodex", "kimi-code", "minimax-code", "minimax-code-cn", "github-copilot", "fireworks", "firepass", "fugu", "gitlab-duo", "cursor", "devin", "jetbrains-junie", "deepseek", "deepinfra", "xai", "groq", "cerebras", "openrouter", "kilo", "vercel-ai-gateway", "zai", "glm-zcode", "mistral", "minimax", "opencode-go", "commandcode-goat", "opencode-zen", "opengateway", "bizrouter", "mara", "synthetic", "cloudflare-ai-gateway", "huggingface", "litellm", "moonshot", "nvidia", "nanogpt", "ollama", "ollama-cloud", "qianfan", "qwen-portal", "sglang", "together", "venice", "vllm", "xiaomi", "xiaomi-token-plan-sgp", "xiaomi-token-plan-ams", "xiaomi-token-plan-cn", "zenmux", "lm-studio", "omlx"];
|
|
58
60
|
export type KnownProvider = (typeof KNOWN_PROVIDERS)[number];
|
|
59
61
|
export declare function isKnownProvider(provider: string): provider is KnownProvider;
|
|
60
62
|
export type Provider = KnownProvider | string;
|
|
@@ -251,6 +253,13 @@ export interface StreamOptions {
|
|
|
251
253
|
* Providers can use this to persist transport/session state between turns.
|
|
252
254
|
*/
|
|
253
255
|
providerSessionState?: Map<string, ProviderSessionState>;
|
|
256
|
+
/**
|
|
257
|
+
* Set by GJC for internal maintenance/one-shot work (context compaction,
|
|
258
|
+
* handoff and branch summaries, utility generations) rather than an
|
|
259
|
+
* interactive user turn. Agent-level providers use it to refuse requests they
|
|
260
|
+
* cannot serve instead of forwarding them to a billed upstream agent.
|
|
261
|
+
*/
|
|
262
|
+
maintenanceCall?: boolean;
|
|
254
263
|
/**
|
|
255
264
|
* Optional callback for inspecting or replacing provider payloads before sending.
|
|
256
265
|
* Return undefined to keep the payload unchanged.
|
|
@@ -306,6 +315,12 @@ export interface StreamOptions {
|
|
|
306
315
|
authCredentialType?: "api_key" | "oauth";
|
|
307
316
|
/** Cursor exec/MCP tool handlers (cursor-agent only). */
|
|
308
317
|
execHandlers?: CursorExecHandlers;
|
|
318
|
+
/**
|
|
319
|
+
* Devin CLI ACP provider configuration (devin-acp only). When absent, the
|
|
320
|
+
* provider spawns `devin acp` from PATH (or `GJC_DEVIN_CLI_PATH`) in the
|
|
321
|
+
* current working directory and applies the default permission policy.
|
|
322
|
+
*/
|
|
323
|
+
devinAcp?: DevinAcpConfig;
|
|
309
324
|
/** Per-attempt identity for execution attribution. Threaded into onPayload/onResponse calls. */
|
|
310
325
|
attemptScope?: AttemptScopeRef;
|
|
311
326
|
}
|
|
@@ -550,6 +565,14 @@ export interface AssistantMessage {
|
|
|
550
565
|
usage: Usage;
|
|
551
566
|
stopReason: StopReason;
|
|
552
567
|
errorMessage?: string;
|
|
568
|
+
/**
|
|
569
|
+
* Bounded, redaction-safe failure classifier for a terminal provider/runtime
|
|
570
|
+
* failure (a safe token matching `[A-Za-z0-9._-]{1,64}`), e.g.
|
|
571
|
+
* `upstream_stream_interrupted`. Set by the provider/agent that owns the
|
|
572
|
+
* classifier; never raw provider text and never a retry-admission fact (retry
|
|
573
|
+
* policy keys on `transportFailure`, not on this diagnostic).
|
|
574
|
+
*/
|
|
575
|
+
errorCode?: string;
|
|
553
576
|
errorKind?: AssistantErrorKind;
|
|
554
577
|
/**
|
|
555
578
|
* Structured, shape-only diagnostic for a terminal local staging-buffer
|
|
@@ -612,17 +635,35 @@ export interface CursorShellStreamCallbacks {
|
|
|
612
635
|
export interface CursorPiCall<TArgs> {
|
|
613
636
|
args: TArgs;
|
|
614
637
|
toolCallId: string;
|
|
638
|
+
/** Per-exec cancellation signal; aborted when the caller aborts or the local exec deadline fires. */
|
|
639
|
+
signal?: AbortSignal;
|
|
640
|
+
/** Marks a started mutation that must settle before Cursor can terminalize the exec. */
|
|
641
|
+
markNonAbortable?: () => void;
|
|
615
642
|
}
|
|
616
643
|
export interface CursorExecHandlers {
|
|
617
|
-
read?: (args: ReadArgs
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
644
|
+
read?: (args: ReadArgs, signal?: AbortSignal,
|
|
645
|
+
/** Marks a started non-abortable operation so the exec terminal waits for settlement. */
|
|
646
|
+
markNonAbortable?: () => void) => Promise<CursorExecHandlerResult<ReadResult>>;
|
|
647
|
+
ls?: (args: LsArgs, signal?: AbortSignal,
|
|
648
|
+
/** Marks a started non-abortable operation so the exec terminal waits for settlement. */
|
|
649
|
+
markNonAbortable?: () => void) => Promise<CursorExecHandlerResult<LsResult>>;
|
|
650
|
+
grep?: (args: GrepArgs, signal?: AbortSignal) => Promise<CursorExecHandlerResult<GrepResult>>;
|
|
651
|
+
write?: (args: WriteArgs, signal?: AbortSignal,
|
|
652
|
+
/** Marks a started non-abortable mutation so the exec terminal waits for settlement. */
|
|
653
|
+
markNonAbortable?: () => void) => Promise<CursorExecHandlerResult<WriteResult>>;
|
|
654
|
+
delete?: (args: DeleteArgs, signal?: AbortSignal,
|
|
655
|
+
/** Marks a started non-abortable mutation so the exec terminal waits for settlement. */
|
|
656
|
+
markNonAbortable?: () => void) => Promise<CursorExecHandlerResult<DeleteResult>>;
|
|
657
|
+
shell?: (args: ShellArgs, signal?: AbortSignal,
|
|
658
|
+
/** Marks a started non-abortable operation so the exec terminal waits for settlement. */
|
|
659
|
+
markNonAbortable?: () => void) => Promise<CursorExecHandlerResult<ShellResult>>;
|
|
660
|
+
shellStream?: (args: ShellArgs, callbacks: CursorShellStreamCallbacks, signal?: AbortSignal,
|
|
661
|
+
/** Marks a started non-abortable operation so the exec terminal waits for settlement. */
|
|
662
|
+
markNonAbortable?: () => void) => Promise<CursorExecHandlerResult<ShellResult>>;
|
|
663
|
+
diagnostics?: (args: DiagnosticsArgs, signal?: AbortSignal) => Promise<CursorExecHandlerResult<DiagnosticsResult>>;
|
|
664
|
+
mcp?: (call: CursorMcpCall, signal?: AbortSignal,
|
|
665
|
+
/** Marks a started non-abortable operation so the exec terminal waits for settlement. */
|
|
666
|
+
markNonAbortable?: () => void) => Promise<CursorExecHandlerResult<McpResult>>;
|
|
626
667
|
piRead?: (call: CursorPiCall<PiReadExecArgs>) => Promise<CursorExecHandlerResult<PiReadExecResult>>;
|
|
627
668
|
piBash?: (call: CursorPiCall<PiBashExecArgs>) => Promise<CursorExecHandlerResult<PiBashExecResult>>;
|
|
628
669
|
piEdit?: (call: CursorPiCall<PiEditExecArgs>) => Promise<CursorExecHandlerResult<PiEditExecResult>>;
|
package/src/types.ts
CHANGED
|
@@ -34,6 +34,7 @@ import type {
|
|
|
34
34
|
WriteArgs,
|
|
35
35
|
WriteResult,
|
|
36
36
|
} from "./providers/cursor/gen/agent_pb";
|
|
37
|
+
import type { DevinAcpConfig, DevinAcpOptions } from "./providers/devin-acp";
|
|
37
38
|
import type { GoogleOptions } from "./providers/google";
|
|
38
39
|
import type { GoogleGeminiCliOptions } from "./providers/google-gemini-cli";
|
|
39
40
|
import type { GoogleVertexOptions } from "./providers/google-vertex";
|
|
@@ -60,6 +61,7 @@ export type KnownApi =
|
|
|
60
61
|
| "google-vertex"
|
|
61
62
|
| "ollama-chat"
|
|
62
63
|
| "cursor-agent"
|
|
64
|
+
| "devin-acp"
|
|
63
65
|
| "kiro-codewhisperer-stream";
|
|
64
66
|
export type Api = KnownApi | (string & {});
|
|
65
67
|
export interface ApiOptionsMap {
|
|
@@ -74,6 +76,7 @@ export interface ApiOptionsMap {
|
|
|
74
76
|
"google-vertex": GoogleVertexOptions;
|
|
75
77
|
"ollama-chat": OllamaChatOptions;
|
|
76
78
|
"cursor-agent": CursorOptions;
|
|
79
|
+
"devin-acp": DevinAcpOptions;
|
|
77
80
|
"kiro-codewhisperer-stream": KiroCodeWhispererOptions;
|
|
78
81
|
}
|
|
79
82
|
// Compile-time exhaustiveness check - this will fail if ApiOptionsMap doesn't have all KnownApi keys
|
|
@@ -153,6 +156,7 @@ export const KNOWN_PROVIDERS = [
|
|
|
153
156
|
"fugu",
|
|
154
157
|
"gitlab-duo",
|
|
155
158
|
"cursor",
|
|
159
|
+
"devin",
|
|
156
160
|
"jetbrains-junie",
|
|
157
161
|
"deepseek",
|
|
158
162
|
"deepinfra",
|
|
@@ -455,6 +459,13 @@ export interface StreamOptions {
|
|
|
455
459
|
* Providers can use this to persist transport/session state between turns.
|
|
456
460
|
*/
|
|
457
461
|
providerSessionState?: Map<string, ProviderSessionState>;
|
|
462
|
+
/**
|
|
463
|
+
* Set by GJC for internal maintenance/one-shot work (context compaction,
|
|
464
|
+
* handoff and branch summaries, utility generations) rather than an
|
|
465
|
+
* interactive user turn. Agent-level providers use it to refuse requests they
|
|
466
|
+
* cannot serve instead of forwarding them to a billed upstream agent.
|
|
467
|
+
*/
|
|
468
|
+
maintenanceCall?: boolean;
|
|
458
469
|
/**
|
|
459
470
|
* Optional callback for inspecting or replacing provider payloads before sending.
|
|
460
471
|
* Return undefined to keep the payload unchanged.
|
|
@@ -520,6 +531,12 @@ export interface StreamOptions {
|
|
|
520
531
|
authCredentialType?: "api_key" | "oauth";
|
|
521
532
|
/** Cursor exec/MCP tool handlers (cursor-agent only). */
|
|
522
533
|
execHandlers?: CursorExecHandlers;
|
|
534
|
+
/**
|
|
535
|
+
* Devin CLI ACP provider configuration (devin-acp only). When absent, the
|
|
536
|
+
* provider spawns `devin acp` from PATH (or `GJC_DEVIN_CLI_PATH`) in the
|
|
537
|
+
* current working directory and applies the default permission policy.
|
|
538
|
+
*/
|
|
539
|
+
devinAcp?: DevinAcpConfig;
|
|
523
540
|
/** Per-attempt identity for execution attribution. Threaded into onPayload/onResponse calls. */
|
|
524
541
|
attemptScope?: AttemptScopeRef;
|
|
525
542
|
}
|
|
@@ -786,6 +803,14 @@ export interface AssistantMessage {
|
|
|
786
803
|
usage: Usage;
|
|
787
804
|
stopReason: StopReason;
|
|
788
805
|
errorMessage?: string;
|
|
806
|
+
/**
|
|
807
|
+
* Bounded, redaction-safe failure classifier for a terminal provider/runtime
|
|
808
|
+
* failure (a safe token matching `[A-Za-z0-9._-]{1,64}`), e.g.
|
|
809
|
+
* `upstream_stream_interrupted`. Set by the provider/agent that owns the
|
|
810
|
+
* classifier; never raw provider text and never a retry-admission fact (retry
|
|
811
|
+
* policy keys on `transportFailure`, not on this diagnostic).
|
|
812
|
+
*/
|
|
813
|
+
errorCode?: string;
|
|
789
814
|
errorKind?: AssistantErrorKind;
|
|
790
815
|
/**
|
|
791
816
|
* Structured, shape-only diagnostic for a terminal local staging-buffer
|
|
@@ -854,21 +879,58 @@ export interface CursorShellStreamCallbacks {
|
|
|
854
879
|
export interface CursorPiCall<TArgs> {
|
|
855
880
|
args: TArgs;
|
|
856
881
|
toolCallId: string;
|
|
882
|
+
/** Per-exec cancellation signal; aborted when the caller aborts or the local exec deadline fires. */
|
|
883
|
+
signal?: AbortSignal;
|
|
884
|
+
/** Marks a started mutation that must settle before Cursor can terminalize the exec. */
|
|
885
|
+
markNonAbortable?: () => void;
|
|
857
886
|
}
|
|
858
887
|
|
|
859
888
|
export interface CursorExecHandlers {
|
|
860
|
-
read?: (
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
889
|
+
read?: (
|
|
890
|
+
args: ReadArgs,
|
|
891
|
+
signal?: AbortSignal,
|
|
892
|
+
/** Marks a started non-abortable operation so the exec terminal waits for settlement. */
|
|
893
|
+
markNonAbortable?: () => void,
|
|
894
|
+
) => Promise<CursorExecHandlerResult<ReadResult>>;
|
|
895
|
+
ls?: (
|
|
896
|
+
args: LsArgs,
|
|
897
|
+
signal?: AbortSignal,
|
|
898
|
+
/** Marks a started non-abortable operation so the exec terminal waits for settlement. */
|
|
899
|
+
markNonAbortable?: () => void,
|
|
900
|
+
) => Promise<CursorExecHandlerResult<LsResult>>;
|
|
901
|
+
grep?: (args: GrepArgs, signal?: AbortSignal) => Promise<CursorExecHandlerResult<GrepResult>>;
|
|
902
|
+
write?: (
|
|
903
|
+
args: WriteArgs,
|
|
904
|
+
signal?: AbortSignal,
|
|
905
|
+
/** Marks a started non-abortable mutation so the exec terminal waits for settlement. */
|
|
906
|
+
markNonAbortable?: () => void,
|
|
907
|
+
) => Promise<CursorExecHandlerResult<WriteResult>>;
|
|
908
|
+
delete?: (
|
|
909
|
+
args: DeleteArgs,
|
|
910
|
+
signal?: AbortSignal,
|
|
911
|
+
/** Marks a started non-abortable mutation so the exec terminal waits for settlement. */
|
|
912
|
+
markNonAbortable?: () => void,
|
|
913
|
+
) => Promise<CursorExecHandlerResult<DeleteResult>>;
|
|
914
|
+
shell?: (
|
|
915
|
+
args: ShellArgs,
|
|
916
|
+
signal?: AbortSignal,
|
|
917
|
+
/** Marks a started non-abortable operation so the exec terminal waits for settlement. */
|
|
918
|
+
markNonAbortable?: () => void,
|
|
919
|
+
) => Promise<CursorExecHandlerResult<ShellResult>>;
|
|
866
920
|
shellStream?: (
|
|
867
921
|
args: ShellArgs,
|
|
868
922
|
callbacks: CursorShellStreamCallbacks,
|
|
923
|
+
signal?: AbortSignal,
|
|
924
|
+
/** Marks a started non-abortable operation so the exec terminal waits for settlement. */
|
|
925
|
+
markNonAbortable?: () => void,
|
|
869
926
|
) => Promise<CursorExecHandlerResult<ShellResult>>;
|
|
870
|
-
diagnostics?: (args: DiagnosticsArgs) => Promise<CursorExecHandlerResult<DiagnosticsResult>>;
|
|
871
|
-
mcp?: (
|
|
927
|
+
diagnostics?: (args: DiagnosticsArgs, signal?: AbortSignal) => Promise<CursorExecHandlerResult<DiagnosticsResult>>;
|
|
928
|
+
mcp?: (
|
|
929
|
+
call: CursorMcpCall,
|
|
930
|
+
signal?: AbortSignal,
|
|
931
|
+
/** Marks a started non-abortable operation so the exec terminal waits for settlement. */
|
|
932
|
+
markNonAbortable?: () => void,
|
|
933
|
+
) => Promise<CursorExecHandlerResult<McpResult>>;
|
|
872
934
|
piRead?: (call: CursorPiCall<PiReadExecArgs>) => Promise<CursorExecHandlerResult<PiReadExecResult>>;
|
|
873
935
|
piBash?: (call: CursorPiCall<PiBashExecArgs>) => Promise<CursorExecHandlerResult<PiBashExecResult>>;
|
|
874
936
|
piEdit?: (call: CursorPiCall<PiEditExecArgs>) => Promise<CursorExecHandlerResult<PiEditExecResult>>;
|
|
@@ -1,6 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Provider-resolved tool-call markers.
|
|
3
|
+
*
|
|
4
|
+
* A provider that executes a tool call itself (Cursor exec-owned calls, or an
|
|
5
|
+
* agent-level ACP provider such as Devin, whose agent runs its own tools) marks
|
|
6
|
+
* the emitted `toolCall` block with this symbol. The agent loop then treats the
|
|
7
|
+
* call as display-only and never dispatches it to a GJC tool. Symbols are used
|
|
8
|
+
* instead of a wire field so the marker exists only in-process and can never
|
|
9
|
+
* round-trip through a transcript or a provider payload.
|
|
10
|
+
*/
|
|
11
|
+
export declare const kProviderResolvedToolCall: unique symbol;
|
|
12
|
+
export type ProviderResolvedCarrier = object & {
|
|
13
|
+
[kProviderResolvedToolCall]?: true;
|
|
4
14
|
};
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
15
|
+
export declare function isProviderResolvedToolCall(block: ProviderResolvedCarrier | null | undefined): boolean;
|
|
16
|
+
export declare function copyProviderResolvedToolCall(target: ProviderResolvedCarrier, source: ProviderResolvedCarrier): void;
|
|
@@ -1,11 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Provider-resolved tool-call markers.
|
|
3
|
+
*
|
|
4
|
+
* A provider that executes a tool call itself (Cursor exec-owned calls, or an
|
|
5
|
+
* agent-level ACP provider such as Devin, whose agent runs its own tools) marks
|
|
6
|
+
* the emitted `toolCall` block with this symbol. The agent loop then treats the
|
|
7
|
+
* call as display-only and never dispatches it to a GJC tool. Symbols are used
|
|
8
|
+
* instead of a wire field so the marker exists only in-process and can never
|
|
9
|
+
* round-trip through a transcript or a provider payload.
|
|
10
|
+
*/
|
|
11
|
+
export const kProviderResolvedToolCall: unique symbol = Symbol.for("@gajae-code/ai.provider-resolved-tool-call.v1");
|
|
2
12
|
|
|
3
|
-
export type
|
|
13
|
+
export type ProviderResolvedCarrier = object & { [kProviderResolvedToolCall]?: true };
|
|
4
14
|
|
|
5
|
-
export function
|
|
6
|
-
return block?.[
|
|
15
|
+
export function isProviderResolvedToolCall(block: ProviderResolvedCarrier | null | undefined): boolean {
|
|
16
|
+
return block?.[kProviderResolvedToolCall] === true;
|
|
7
17
|
}
|
|
8
18
|
|
|
9
|
-
export function
|
|
10
|
-
if (source[
|
|
19
|
+
export function copyProviderResolvedToolCall(target: ProviderResolvedCarrier, source: ProviderResolvedCarrier): void {
|
|
20
|
+
if (source[kProviderResolvedToolCall] === true) target[kProviderResolvedToolCall] = true;
|
|
11
21
|
}
|
|
@@ -5,6 +5,7 @@ import { getBundledModels } from "../../models";
|
|
|
5
5
|
import { CURSOR_CLIENT_VERSION } from "../../providers/cursor/client-version";
|
|
6
6
|
import { GetUsableModelsRequestSchema, GetUsableModelsResponseSchema } from "../../providers/cursor/gen/agent_pb";
|
|
7
7
|
import type { Model } from "../../types";
|
|
8
|
+
import { isSafeCatalogModelId } from "./openai-compatible";
|
|
8
9
|
|
|
9
10
|
const CURSOR_DEFAULT_BASE_URL = "https://api2.cursor.sh";
|
|
10
11
|
const CURSOR_GET_USABLE_MODELS_PATH = "/agent.v1.AgentService/GetUsableModels";
|
|
@@ -331,10 +332,10 @@ function normalizeCursorModel(
|
|
|
331
332
|
}
|
|
332
333
|
|
|
333
334
|
const details = parsedModel.data;
|
|
334
|
-
|
|
335
|
-
if (!id) {
|
|
335
|
+
if (!isSafeCatalogModelId(details.modelId)) {
|
|
336
336
|
return null;
|
|
337
337
|
}
|
|
338
|
+
const id = details.modelId.trim();
|
|
338
339
|
|
|
339
340
|
const name = pickModelDisplayName(details, id);
|
|
340
341
|
const reference = references.get(id);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type FallbackTriggerClass = "rate_limit" | "quota" | "auth" | "server" | "unknown" | "other";
|
|
1
|
+
export type FallbackTriggerClass = "rate_limit" | "quota" | "auth" | "credential" | "server" | "unknown" | "other";
|
|
2
2
|
/**
|
|
3
3
|
* Refinement of an `auth` trigger.
|
|
4
4
|
*
|
|
@@ -50,6 +50,8 @@ export interface TransportFailureFacts {
|
|
|
50
50
|
anthropicErrorType?: string;
|
|
51
51
|
/** OpenAI's typed `error.code`, preserved separately at the transport boundary. */
|
|
52
52
|
openaiErrorCode?: string;
|
|
53
|
+
/** Provider-authoritative model rejection that is specific to the active credential. */
|
|
54
|
+
credentialModelUnavailable?: true;
|
|
53
55
|
headers?: Record<string, string>;
|
|
54
56
|
/** Safe request-size observation for retry amplification policy. Never contains body content. */
|
|
55
57
|
requestBytes?: number;
|
|
@@ -84,6 +86,7 @@ export interface FallbackTriggerInput {
|
|
|
84
86
|
status?: number;
|
|
85
87
|
providerCode?: string;
|
|
86
88
|
code?: string;
|
|
89
|
+
credentialModelUnavailable?: boolean;
|
|
87
90
|
headers?: TransportHeaders;
|
|
88
91
|
response?: {
|
|
89
92
|
status?: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type FallbackTriggerClass = "rate_limit" | "quota" | "auth" | "server" | "unknown" | "other";
|
|
1
|
+
export type FallbackTriggerClass = "rate_limit" | "quota" | "auth" | "credential" | "server" | "unknown" | "other";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Refinement of an `auth` trigger.
|
|
@@ -55,6 +55,8 @@ export interface TransportFailureFacts {
|
|
|
55
55
|
anthropicErrorType?: string;
|
|
56
56
|
/** OpenAI's typed `error.code`, preserved separately at the transport boundary. */
|
|
57
57
|
openaiErrorCode?: string;
|
|
58
|
+
/** Provider-authoritative model rejection that is specific to the active credential. */
|
|
59
|
+
credentialModelUnavailable?: true;
|
|
58
60
|
headers?: Record<string, string>;
|
|
59
61
|
/** Safe request-size observation for retry amplification policy. Never contains body content. */
|
|
60
62
|
requestBytes?: number;
|
|
@@ -109,6 +111,7 @@ export interface FallbackTriggerInput {
|
|
|
109
111
|
status?: number;
|
|
110
112
|
providerCode?: string;
|
|
111
113
|
code?: string;
|
|
114
|
+
credentialModelUnavailable?: boolean;
|
|
112
115
|
headers?: TransportHeaders;
|
|
113
116
|
response?: { status?: number; headers?: TransportHeaders };
|
|
114
117
|
error?: { code?: string; type?: string };
|
|
@@ -239,6 +242,7 @@ export function transportFailureFacts(
|
|
|
239
242
|
const endpointClassValue = propertyOf(value, "endpointClass");
|
|
240
243
|
const endpointClass =
|
|
241
244
|
endpointClassValue === "canonical" || endpointClassValue === "custom" ? endpointClassValue : undefined;
|
|
245
|
+
const credentialModelUnavailable = propertyOf(value, "credentialModelUnavailable") === true;
|
|
242
246
|
if (
|
|
243
247
|
status === undefined &&
|
|
244
248
|
headers === undefined &&
|
|
@@ -253,6 +257,7 @@ export function transportFailureFacts(
|
|
|
253
257
|
// must not materialize facts that would disqualify an unrelated
|
|
254
258
|
// bare-default retry.
|
|
255
259
|
providerCode !== SERVER_OVERLOADED_PROVIDER_CODE &&
|
|
260
|
+
!credentialModelUnavailable &&
|
|
256
261
|
requestBytes === undefined &&
|
|
257
262
|
firstEventElapsedMs === undefined &&
|
|
258
263
|
firstEventTimeoutMs === undefined &&
|
|
@@ -267,6 +272,7 @@ export function transportFailureFacts(
|
|
|
267
272
|
providerCode,
|
|
268
273
|
anthropicErrorType,
|
|
269
274
|
openaiErrorCode,
|
|
275
|
+
...(credentialModelUnavailable ? { credentialModelUnavailable: true as const } : {}),
|
|
270
276
|
headers,
|
|
271
277
|
...(requestBytes === undefined ? {} : { requestBytes }),
|
|
272
278
|
...(firstEventElapsedMs === undefined ? {} : { firstEventElapsedMs }),
|
|
@@ -379,10 +385,11 @@ export function classifyFallbackTrigger(
|
|
|
379
385
|
// classify without a status, so it is matched case-sensitively — the same
|
|
380
386
|
// exactness the parser and the session admission use.
|
|
381
387
|
const rawCode = rawCodes[0] ?? rawCodes[1] ?? rawCodes[2];
|
|
382
|
-
const triggerClass: FallbackTriggerClass =
|
|
383
|
-
|
|
384
|
-
code ===
|
|
385
|
-
|
|
388
|
+
const triggerClass: FallbackTriggerClass = facts.credentialModelUnavailable
|
|
389
|
+
? "credential"
|
|
390
|
+
: code === STREAM_FIRST_EVENT_TIMEOUT_PROVIDER_CODE ||
|
|
391
|
+
code === EMPTY_RESPONSE_PROVIDER_CODE ||
|
|
392
|
+
(facts.status === undefined && rawCode === SERVER_OVERLOADED_PROVIDER_CODE)
|
|
386
393
|
? "server"
|
|
387
394
|
: isQuotaCode(code)
|
|
388
395
|
? "quota"
|
package/src/utils.d.ts
CHANGED
|
@@ -7,6 +7,19 @@ export declare function toNumber(value: unknown): number | undefined;
|
|
|
7
7
|
export declare function toPositiveNumber(value: unknown, fallback: number): number;
|
|
8
8
|
export declare function toBoolean(value: unknown): boolean | undefined;
|
|
9
9
|
export declare function normalizeToolCallId(id: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Wire-facing tool call id for a canonical ToolCall served to a foreign client.
|
|
12
|
+
*
|
|
13
|
+
* Responses-backed upstreams (Codex, OpenAI Responses) encode the tool call as
|
|
14
|
+
* `${call_id}|${item_id}` in `ToolCall.id` so their own replay can recover the
|
|
15
|
+
* item id. That encoding is gjc-internal: a downstream OpenAI-format client
|
|
16
|
+
* (OpenCodex, another gjc) truncates the compound value at its own 64-char
|
|
17
|
+
* limit and can no longer pair its tool output with the call it echoed back,
|
|
18
|
+
* so the whole chained turn is rejected with "No tool output found". Emit only
|
|
19
|
+
* the `call_id` half on the wire; the item id travels separately as the item
|
|
20
|
+
* `id` where the wire format has one.
|
|
21
|
+
*/
|
|
22
|
+
export declare function wireToolCallId(id: string): string;
|
|
10
23
|
type ResponsesToolItemIdPrefix = "fc" | "ctc";
|
|
11
24
|
export declare function normalizeResponsesToolCallId(id: string, itemPrefix?: ResponsesToolItemIdPrefix): {
|
|
12
25
|
callId: string;
|
package/src/utils.ts
CHANGED
|
@@ -64,6 +64,23 @@ export function normalizeToolCallId(id: string): string {
|
|
|
64
64
|
return sanitized.length > 64 ? sanitized.slice(0, 64) : sanitized;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Wire-facing tool call id for a canonical ToolCall served to a foreign client.
|
|
69
|
+
*
|
|
70
|
+
* Responses-backed upstreams (Codex, OpenAI Responses) encode the tool call as
|
|
71
|
+
* `${call_id}|${item_id}` in `ToolCall.id` so their own replay can recover the
|
|
72
|
+
* item id. That encoding is gjc-internal: a downstream OpenAI-format client
|
|
73
|
+
* (OpenCodex, another gjc) truncates the compound value at its own 64-char
|
|
74
|
+
* limit and can no longer pair its tool output with the call it echoed back,
|
|
75
|
+
* so the whole chained turn is rejected with "No tool output found". Emit only
|
|
76
|
+
* the `call_id` half on the wire; the item id travels separately as the item
|
|
77
|
+
* `id` where the wire format has one.
|
|
78
|
+
*/
|
|
79
|
+
export function wireToolCallId(id: string): string {
|
|
80
|
+
const separator = id.indexOf("|");
|
|
81
|
+
return separator === -1 ? id : id.slice(0, separator);
|
|
82
|
+
}
|
|
83
|
+
|
|
67
84
|
type ResponsesToolItemIdPrefix = "fc" | "ctc";
|
|
68
85
|
|
|
69
86
|
export function normalizeResponsesToolCallId(
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Model entitlement facts shared by Codex credential selection and provider
|
|
3
|
-
* error presentation.
|
|
4
|
-
*
|
|
5
|
-
* GPT-5.6 Sol is a Pro-tier ChatGPT Codex model. The usage endpoint is the
|
|
6
|
-
* authority for the account tier; this module only names the model policy and
|
|
7
|
-
* keeps the provider's deterministic rejection wording in one place.
|
|
8
|
-
*/
|
|
9
|
-
export type OpenAICodexProEntitlement = "entitled" | "denied" | "unknown";
|
|
10
|
-
/**
|
|
11
|
-
* Classify a ChatGPT `plan_type` for strict Pro-tier Codex models.
|
|
12
|
-
*
|
|
13
|
-
* The usage endpoint remains authoritative: only exact, documented tier names
|
|
14
|
-
* are classified. Known Free/Plus tiers can be rejected locally, while missing
|
|
15
|
-
* or unfamiliar values stay unknown and reach the provider instead of being
|
|
16
|
-
* guessed from a substring.
|
|
17
|
-
*/
|
|
18
|
-
export declare function classifyOpenAICodexProEntitlement(planType: string | undefined): OpenAICodexProEntitlement;
|
|
19
|
-
export declare function requiresOpenAICodexProModel(provider: string, modelId: string | undefined): boolean;
|
|
20
|
-
export declare function requiresStrictOpenAICodexProModel(provider: string, modelId: string | undefined): boolean;
|
|
21
|
-
export declare function isOpenAICodexChatGPTEntitlementError(message: string | undefined, code?: string): boolean;
|
|
22
|
-
export declare function formatOpenAICodexChatGPTEntitlementError(modelId: string | undefined): string;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Model entitlement facts shared by Codex credential selection and provider
|
|
3
|
-
* error presentation.
|
|
4
|
-
*
|
|
5
|
-
* GPT-5.6 Sol is a Pro-tier ChatGPT Codex model. The usage endpoint is the
|
|
6
|
-
* authority for the account tier; this module only names the model policy and
|
|
7
|
-
* keeps the provider's deterministic rejection wording in one place.
|
|
8
|
-
*/
|
|
9
|
-
export type OpenAICodexProEntitlement = "entitled" | "denied" | "unknown";
|
|
10
|
-
/**
|
|
11
|
-
* Classify a ChatGPT `plan_type` for strict Pro-tier Codex models.
|
|
12
|
-
*
|
|
13
|
-
* The usage endpoint remains authoritative: only exact, documented tier names
|
|
14
|
-
* are classified. Known Free/Plus tiers can be rejected locally, while missing
|
|
15
|
-
* or unfamiliar values stay unknown and reach the provider instead of being
|
|
16
|
-
* guessed from a substring.
|
|
17
|
-
*/
|
|
18
|
-
export declare function classifyOpenAICodexProEntitlement(planType: string | undefined): OpenAICodexProEntitlement;
|
|
19
|
-
export declare function requiresOpenAICodexProModel(provider: string, modelId: string | undefined): boolean;
|
|
20
|
-
export declare function requiresStrictOpenAICodexProModel(provider: string, modelId: string | undefined): boolean;
|
|
21
|
-
export declare function isOpenAICodexChatGPTEntitlementError(message: string | undefined, code?: string): boolean;
|
|
22
|
-
export declare function formatOpenAICodexChatGPTEntitlementError(modelId: string | undefined): string;
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Model entitlement facts shared by Codex credential selection and provider
|
|
3
|
-
* error presentation.
|
|
4
|
-
*
|
|
5
|
-
* GPT-5.6 Sol is a Pro-tier ChatGPT Codex model. The usage endpoint is the
|
|
6
|
-
* authority for the account tier; this module only names the model policy and
|
|
7
|
-
* keeps the provider's deterministic rejection wording in one place.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
const OPENAI_CODEX_PRO_ENTITLED_PLAN_TYPES = new Set(["pro", "business", "enterprise", "team"]);
|
|
11
|
-
const OPENAI_CODEX_PRO_DENIED_PLAN_TYPES = new Set(["free", "plus"]);
|
|
12
|
-
|
|
13
|
-
export type OpenAICodexProEntitlement = "entitled" | "denied" | "unknown";
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Classify a ChatGPT `plan_type` for strict Pro-tier Codex models.
|
|
17
|
-
*
|
|
18
|
-
* The usage endpoint remains authoritative: only exact, documented tier names
|
|
19
|
-
* are classified. Known Free/Plus tiers can be rejected locally, while missing
|
|
20
|
-
* or unfamiliar values stay unknown and reach the provider instead of being
|
|
21
|
-
* guessed from a substring.
|
|
22
|
-
*/
|
|
23
|
-
export function classifyOpenAICodexProEntitlement(planType: string | undefined): OpenAICodexProEntitlement {
|
|
24
|
-
const normalized = planType?.trim().toLowerCase();
|
|
25
|
-
if (!normalized) return "unknown";
|
|
26
|
-
if (OPENAI_CODEX_PRO_ENTITLED_PLAN_TYPES.has(normalized)) return "entitled";
|
|
27
|
-
if (OPENAI_CODEX_PRO_DENIED_PLAN_TYPES.has(normalized)) return "denied";
|
|
28
|
-
return "unknown";
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export function requiresOpenAICodexProModel(provider: string, modelId: string | undefined): boolean {
|
|
32
|
-
return (
|
|
33
|
-
provider === "openai-codex" &&
|
|
34
|
-
typeof modelId === "string" &&
|
|
35
|
-
(modelId.toLowerCase().includes("-spark") || modelId.toLowerCase() === "gpt-5.6-sol")
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function requiresStrictOpenAICodexProModel(provider: string, modelId: string | undefined): boolean {
|
|
40
|
-
return provider === "openai-codex" && modelId?.toLowerCase() === "gpt-5.6-sol";
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function isOpenAICodexChatGPTEntitlementError(message: string | undefined, code?: string): boolean {
|
|
44
|
-
return (
|
|
45
|
-
/\bnot supported when using codex with a chatgpt account\b/i.test(message ?? "") &&
|
|
46
|
-
(code === undefined || code.toLowerCase() === "invalid_request_error")
|
|
47
|
-
);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function formatOpenAICodexChatGPTEntitlementError(modelId: string | undefined): string {
|
|
51
|
-
const safeModelId = modelId
|
|
52
|
-
?.replace(/[\x00-\x1f\x7f-\x9f]+/gu, " ")
|
|
53
|
-
.trim()
|
|
54
|
-
.slice(0, 128);
|
|
55
|
-
const model = safeModelId ? ` model "${safeModelId}"` : " model";
|
|
56
|
-
return `This ChatGPT Codex account cannot use${model}. Select a model available to this ChatGPT account, such as "gpt-5.5", or use an API-key credential that supports the model.`;
|
|
57
|
-
}
|