@omnicross/core 0.1.0 → 0.1.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 (139) hide show
  1. package/dist/ApiConverter.cjs +799 -0
  2. package/dist/ApiConverter.d.cts +82 -0
  3. package/dist/ApiConverter.d.ts +82 -0
  4. package/dist/ApiConverter.js +763 -0
  5. package/dist/BuiltinToolExecutor-BluWyeob.d.ts +81 -0
  6. package/dist/BuiltinToolExecutor-CS2WpXhM.d.cts +81 -0
  7. package/dist/CompletionService-7fCmKAP3.d.ts +212 -0
  8. package/dist/CompletionService-DtOF_War.d.cts +212 -0
  9. package/dist/{ProviderProxy-f_8ziIhW.d.cts → ProviderProxy-C-xqrkKi.d.ts} +7 -2
  10. package/dist/{ProviderProxy-vjt8sQQk.d.ts → ProviderProxy-CnMQYN59.d.cts} +7 -2
  11. package/dist/completion/BuiltinToolExecutor.cjs +327 -0
  12. package/dist/completion/BuiltinToolExecutor.d.cts +4 -0
  13. package/dist/completion/BuiltinToolExecutor.d.ts +4 -0
  14. package/dist/completion/BuiltinToolExecutor.js +296 -0
  15. package/dist/completion/CompletionService.cjs +3487 -0
  16. package/dist/completion/CompletionService.d.cts +21 -0
  17. package/dist/completion/CompletionService.d.ts +21 -0
  18. package/dist/completion/CompletionService.js +3461 -0
  19. package/dist/completion/NativeSearchInjector.cjs +196 -0
  20. package/dist/completion/NativeSearchInjector.d.cts +42 -0
  21. package/dist/completion/NativeSearchInjector.d.ts +42 -0
  22. package/dist/completion/NativeSearchInjector.js +167 -0
  23. package/dist/completion/ProviderSearchInjector.cjs +87 -0
  24. package/dist/completion/ProviderSearchInjector.d.cts +47 -0
  25. package/dist/completion/ProviderSearchInjector.d.ts +47 -0
  26. package/dist/completion/ProviderSearchInjector.js +60 -0
  27. package/dist/completion/native-search-types.cjs +67 -0
  28. package/dist/completion/native-search-types.d.cts +3 -0
  29. package/dist/completion/native-search-types.d.ts +3 -0
  30. package/dist/completion/native-search-types.js +38 -0
  31. package/dist/completion/openrouter-headers.cjs +72 -0
  32. package/dist/completion/openrouter-headers.d.cts +44 -0
  33. package/dist/completion/openrouter-headers.d.ts +44 -0
  34. package/dist/completion/openrouter-headers.js +42 -0
  35. package/dist/completion/openrouter-models.cjs +86 -0
  36. package/dist/completion/openrouter-models.d.cts +27 -0
  37. package/dist/completion/openrouter-models.d.ts +27 -0
  38. package/dist/completion/openrouter-models.js +59 -0
  39. package/dist/completion/types.cjs +18 -0
  40. package/dist/completion/types.d.cts +3 -0
  41. package/dist/completion/types.d.ts +3 -0
  42. package/dist/completion/types.js +0 -0
  43. package/dist/completion/url-builder.cjs +138 -0
  44. package/dist/completion/url-builder.d.cts +87 -0
  45. package/dist/completion/url-builder.d.ts +87 -0
  46. package/dist/completion/url-builder.js +104 -0
  47. package/dist/completion.d.cts +148 -7
  48. package/dist/completion.d.ts +148 -7
  49. package/dist/index.cjs +1 -0
  50. package/dist/index.d.cts +27 -90
  51. package/dist/index.d.ts +27 -90
  52. package/dist/index.js +1 -0
  53. package/dist/outbound-api/routeResolver.cjs +221 -0
  54. package/dist/outbound-api/routeResolver.d.cts +18 -0
  55. package/dist/outbound-api/routeResolver.d.ts +18 -0
  56. package/dist/outbound-api/routeResolver.js +192 -0
  57. package/dist/outbound-api/subscriptionRegistryPort.d.cts +5 -2
  58. package/dist/outbound-api/subscriptionRegistryPort.d.ts +5 -2
  59. package/dist/outbound-api/types.cjs +18 -0
  60. package/dist/{types-CbCN2NQP.d.ts → outbound-api/types.d.cts} +17 -3
  61. package/dist/{types-CGGrKqC_.d.cts → outbound-api/types.d.ts} +17 -3
  62. package/dist/outbound-api/types.js +0 -0
  63. package/dist/outbound-api.cjs +1 -0
  64. package/dist/outbound-api.d.cts +14 -87
  65. package/dist/outbound-api.d.ts +14 -87
  66. package/dist/outbound-api.js +1 -0
  67. package/dist/pipeline/AuthSource.cjs +18 -0
  68. package/dist/pipeline/AuthSource.d.cts +101 -0
  69. package/dist/pipeline/AuthSource.d.ts +101 -0
  70. package/dist/pipeline/AuthSource.js +0 -0
  71. package/dist/pipeline/LlmConfigProviderAuth.cjs +169 -0
  72. package/dist/pipeline/LlmConfigProviderAuth.d.cts +86 -0
  73. package/dist/pipeline/LlmConfigProviderAuth.d.ts +86 -0
  74. package/dist/pipeline/LlmConfigProviderAuth.js +142 -0
  75. package/dist/pipeline/SubscriptionAuthSource.d.cts +165 -3
  76. package/dist/pipeline/SubscriptionAuthSource.d.ts +165 -3
  77. package/dist/pipeline/executeProviderCall.cjs +70 -0
  78. package/dist/pipeline/executeProviderCall.d.cts +149 -0
  79. package/dist/pipeline/executeProviderCall.d.ts +149 -0
  80. package/dist/pipeline/executeProviderCall.js +45 -0
  81. package/dist/pipeline/resolveProviderChain.cjs +47 -0
  82. package/dist/pipeline/resolveProviderChain.d.cts +58 -0
  83. package/dist/pipeline/resolveProviderChain.d.ts +58 -0
  84. package/dist/pipeline/resolveProviderChain.js +22 -0
  85. package/dist/pipeline/resolveSubscriptionChain.cjs +68 -0
  86. package/dist/pipeline/resolveSubscriptionChain.d.cts +68 -0
  87. package/dist/pipeline/resolveSubscriptionChain.d.ts +68 -0
  88. package/dist/pipeline/resolveSubscriptionChain.js +43 -0
  89. package/dist/ports/provider-config-source.cjs +18 -0
  90. package/dist/ports/provider-config-source.d.cts +51 -0
  91. package/dist/ports/provider-config-source.d.ts +51 -0
  92. package/dist/ports/provider-config-source.js +0 -0
  93. package/dist/ports/web-search-backend.cjs +18 -0
  94. package/dist/ports/web-search-backend.d.cts +29 -0
  95. package/dist/ports/web-search-backend.d.ts +29 -0
  96. package/dist/ports/web-search-backend.js +0 -0
  97. package/dist/ports.d.cts +10 -7
  98. package/dist/ports.d.ts +10 -7
  99. package/dist/provider-proxy/ProviderProxy.cjs +4643 -0
  100. package/dist/provider-proxy/ProviderProxy.d.cts +16 -0
  101. package/dist/provider-proxy/ProviderProxy.d.ts +16 -0
  102. package/dist/provider-proxy/ProviderProxy.js +4618 -0
  103. package/dist/provider-proxy/ingress/providerProxyShared.d.cts +5 -2
  104. package/dist/provider-proxy/ingress/providerProxyShared.d.ts +5 -2
  105. package/dist/provider-proxy/types.d.cts +406 -8
  106. package/dist/provider-proxy/types.d.ts +406 -8
  107. package/dist/provider-proxy.cjs +1 -0
  108. package/dist/provider-proxy.d.cts +8 -5
  109. package/dist/provider-proxy.d.ts +8 -5
  110. package/dist/provider-proxy.js +1 -0
  111. package/dist/routeResolver-BrbK6ja9.d.cts +88 -0
  112. package/dist/routeResolver-HE-ZO0fO.d.ts +88 -0
  113. package/dist/transformer/anthropicBetaInject.cjs +51 -0
  114. package/dist/transformer/anthropicBetaInject.d.cts +20 -0
  115. package/dist/transformer/anthropicBetaInject.d.ts +20 -0
  116. package/dist/transformer/anthropicBetaInject.js +25 -0
  117. package/dist/transformer/transformers/AnthropicTransformer.cjs +1017 -0
  118. package/dist/transformer/transformers/AnthropicTransformer.d.cts +148 -0
  119. package/dist/transformer/transformers/AnthropicTransformer.d.ts +148 -0
  120. package/dist/transformer/transformers/AnthropicTransformer.js +990 -0
  121. package/dist/transformer/transformers/ReasoningTransformer.cjs +273 -0
  122. package/dist/transformer/transformers/ReasoningTransformer.d.cts +47 -0
  123. package/dist/transformer/transformers/ReasoningTransformer.d.ts +47 -0
  124. package/dist/transformer/transformers/ReasoningTransformer.js +253 -0
  125. package/dist/transformer/transformers.cjs +3206 -0
  126. package/dist/transformer/transformers.d.cts +100 -0
  127. package/dist/transformer/transformers.d.ts +100 -0
  128. package/dist/transformer/transformers.js +3174 -0
  129. package/dist/transformer.d.cts +8 -31
  130. package/dist/transformer.d.ts +8 -31
  131. package/dist/types-BScIHmPr.d.cts +153 -0
  132. package/dist/types-BScIHmPr.d.ts +153 -0
  133. package/package.json +3 -3
  134. package/dist/SubscriptionAuthSource-Cr4fVEYY.d.cts +0 -264
  135. package/dist/SubscriptionAuthSource-D89zmiSS.d.ts +0 -264
  136. package/dist/index-BTSmc9Sm.d.ts +0 -645
  137. package/dist/index-DXazdTzZ.d.cts +0 -645
  138. package/dist/types-DCzHkhJt.d.ts +0 -467
  139. package/dist/types-DZIQbgp0.d.cts +0 -467
@@ -0,0 +1,86 @@
1
+ import { LLMProvider } from '@omnicross/contracts/llm-config';
2
+ import { A as ApiKeyPoolService } from '../ApiKeyPoolService-BmMkau07.cjs';
3
+ import { AuthSource, AuthApplyHints, AuthResultOutcome } from './AuthSource.cjs';
4
+
5
+ /**
6
+ * LlmConfigProviderAuth — `AuthSource` for LLM-config provider rows.
7
+ *
8
+ * Phase 2 of the `provider-request-pipeline` OpenSpec change (design D3, task 4.2).
9
+ *
10
+ * Wraps the two pieces that authenticate a normal (non-subscription) provider
11
+ * request today:
12
+ *
13
+ * - `getProviderHeaders(provider, apiKey)` — the format-specific auth
14
+ * headers (x-api-key / Authorization Bearer / x-goog-api-key / api-key)
15
+ * plus content-type and the OpenRouter app-attribution headers. `applyHeaders`
16
+ * merges these into the caller's header object VERBATIM (same output as a
17
+ * direct `getProviderHeaders` call).
18
+ * - `ApiKeyPoolService` — session-affine key selection + 429/529/401/403
19
+ * rotation. `onResult` reproduces the reportable-status branch of
20
+ * the host engine adapter's `callWithPoolReporting` (report → re-bind →
21
+ * return the new key) and the success branch (`reportSuccess`).
22
+ *
23
+ * IMPORTANT (Phase 2 scope): this class is DEFINED + unit-tested in isolation
24
+ * only. NO caller routes through it yet — `executeProviderCall` is unchanged
25
+ * and the rotation INTEGRATION is Phase 3 (D5). Do not wire `onResult` into a
26
+ * fetch loop in this phase.
27
+ *
28
+ * @module pipeline/LlmConfigProviderAuth
29
+ */
30
+
31
+ interface LlmConfigProviderAuthOptions {
32
+ /** Provider row whose auth format + key drives header assembly. */
33
+ provider: LLMProvider;
34
+ /** Resolved API key string to authenticate with (post env-ref resolution). */
35
+ apiKey: string;
36
+ /**
37
+ * Pool service for rotation, when this request is pool-backed. Omit (or pass
38
+ * `null`) for legacy single-key requests — `onResult` then never touches the
39
+ * pool (matching `fromPool === false`).
40
+ */
41
+ apiKeyPool?: ApiKeyPoolService | null;
42
+ /** Provider id the pool should report/select against (the ACTUAL provider
43
+ * whose key was resolved, post-routing). Required for pool participation. */
44
+ providerId?: string;
45
+ /** Session id for pool affinity + rebind. Required for pool participation. */
46
+ sessionId?: string | null;
47
+ }
48
+ declare class LlmConfigProviderAuth implements AuthSource {
49
+ private readonly provider;
50
+ private readonly apiKeyPool;
51
+ private readonly providerId;
52
+ private readonly sessionId;
53
+ /**
54
+ * The current resolved key. Mutable so a Phase-3 caller can read the
55
+ * rotated key after `onResult`; this phase it is only set at construction
56
+ * and updated inside `onResult` (mirroring the inline re-point in
57
+ * `callWithPoolReporting`).
58
+ */
59
+ apiKey: string;
60
+ constructor(opts: LlmConfigProviderAuthOptions);
61
+ /**
62
+ * Merge the provider auth headers (and content-type / OpenRouter app
63
+ * headers) into `headers`, exactly as a direct `getProviderHeaders` call
64
+ * would produce them. `hints` are accepted for contract symmetry but the
65
+ * provider-key path does not vary headers by URL/model.
66
+ */
67
+ applyHeaders(headers: Record<string, string>, _hints: AuthApplyHints): void;
68
+ /**
69
+ * React to the final HTTP status — the pool-rotation seam (design D5).
70
+ *
71
+ * Reproduces `callWithPoolReporting`'s reportable + success branches:
72
+ * - reportable status (429/529/401/403) on a pool-backed request →
73
+ * `reportError(providerId, sessionId, status)`; when it hands back a
74
+ * `newKey` the session was re-bound, so we adopt it (`this.apiKey`) and
75
+ * return `{ rebound: true, newKey }`. When no key is available it returns
76
+ * `{ rebound: false }` (the session is still cooled/disabled by the report).
77
+ * - success / any 2xx → `reportSuccess(sessionId)`; `{ rebound: false }`.
78
+ * - non-reportable, non-success, or non-pool request → no-op
79
+ * `{ rebound: false }`.
80
+ *
81
+ * NOTE: no caller invokes this in Phase 2; it is unit-tested in isolation.
82
+ */
83
+ onResult(status: number | null): Promise<AuthResultOutcome>;
84
+ }
85
+
86
+ export { LlmConfigProviderAuth, type LlmConfigProviderAuthOptions };
@@ -0,0 +1,86 @@
1
+ import { LLMProvider } from '@omnicross/contracts/llm-config';
2
+ import { A as ApiKeyPoolService } from '../ApiKeyPoolService-BmMkau07.js';
3
+ import { AuthSource, AuthApplyHints, AuthResultOutcome } from './AuthSource.js';
4
+
5
+ /**
6
+ * LlmConfigProviderAuth — `AuthSource` for LLM-config provider rows.
7
+ *
8
+ * Phase 2 of the `provider-request-pipeline` OpenSpec change (design D3, task 4.2).
9
+ *
10
+ * Wraps the two pieces that authenticate a normal (non-subscription) provider
11
+ * request today:
12
+ *
13
+ * - `getProviderHeaders(provider, apiKey)` — the format-specific auth
14
+ * headers (x-api-key / Authorization Bearer / x-goog-api-key / api-key)
15
+ * plus content-type and the OpenRouter app-attribution headers. `applyHeaders`
16
+ * merges these into the caller's header object VERBATIM (same output as a
17
+ * direct `getProviderHeaders` call).
18
+ * - `ApiKeyPoolService` — session-affine key selection + 429/529/401/403
19
+ * rotation. `onResult` reproduces the reportable-status branch of
20
+ * the host engine adapter's `callWithPoolReporting` (report → re-bind →
21
+ * return the new key) and the success branch (`reportSuccess`).
22
+ *
23
+ * IMPORTANT (Phase 2 scope): this class is DEFINED + unit-tested in isolation
24
+ * only. NO caller routes through it yet — `executeProviderCall` is unchanged
25
+ * and the rotation INTEGRATION is Phase 3 (D5). Do not wire `onResult` into a
26
+ * fetch loop in this phase.
27
+ *
28
+ * @module pipeline/LlmConfigProviderAuth
29
+ */
30
+
31
+ interface LlmConfigProviderAuthOptions {
32
+ /** Provider row whose auth format + key drives header assembly. */
33
+ provider: LLMProvider;
34
+ /** Resolved API key string to authenticate with (post env-ref resolution). */
35
+ apiKey: string;
36
+ /**
37
+ * Pool service for rotation, when this request is pool-backed. Omit (or pass
38
+ * `null`) for legacy single-key requests — `onResult` then never touches the
39
+ * pool (matching `fromPool === false`).
40
+ */
41
+ apiKeyPool?: ApiKeyPoolService | null;
42
+ /** Provider id the pool should report/select against (the ACTUAL provider
43
+ * whose key was resolved, post-routing). Required for pool participation. */
44
+ providerId?: string;
45
+ /** Session id for pool affinity + rebind. Required for pool participation. */
46
+ sessionId?: string | null;
47
+ }
48
+ declare class LlmConfigProviderAuth implements AuthSource {
49
+ private readonly provider;
50
+ private readonly apiKeyPool;
51
+ private readonly providerId;
52
+ private readonly sessionId;
53
+ /**
54
+ * The current resolved key. Mutable so a Phase-3 caller can read the
55
+ * rotated key after `onResult`; this phase it is only set at construction
56
+ * and updated inside `onResult` (mirroring the inline re-point in
57
+ * `callWithPoolReporting`).
58
+ */
59
+ apiKey: string;
60
+ constructor(opts: LlmConfigProviderAuthOptions);
61
+ /**
62
+ * Merge the provider auth headers (and content-type / OpenRouter app
63
+ * headers) into `headers`, exactly as a direct `getProviderHeaders` call
64
+ * would produce them. `hints` are accepted for contract symmetry but the
65
+ * provider-key path does not vary headers by URL/model.
66
+ */
67
+ applyHeaders(headers: Record<string, string>, _hints: AuthApplyHints): void;
68
+ /**
69
+ * React to the final HTTP status — the pool-rotation seam (design D5).
70
+ *
71
+ * Reproduces `callWithPoolReporting`'s reportable + success branches:
72
+ * - reportable status (429/529/401/403) on a pool-backed request →
73
+ * `reportError(providerId, sessionId, status)`; when it hands back a
74
+ * `newKey` the session was re-bound, so we adopt it (`this.apiKey`) and
75
+ * return `{ rebound: true, newKey }`. When no key is available it returns
76
+ * `{ rebound: false }` (the session is still cooled/disabled by the report).
77
+ * - success / any 2xx → `reportSuccess(sessionId)`; `{ rebound: false }`.
78
+ * - non-reportable, non-success, or non-pool request → no-op
79
+ * `{ rebound: false }`.
80
+ *
81
+ * NOTE: no caller invokes this in Phase 2; it is unit-tested in isolation.
82
+ */
83
+ onResult(status: number | null): Promise<AuthResultOutcome>;
84
+ }
85
+
86
+ export { LlmConfigProviderAuth, type LlmConfigProviderAuthOptions };
@@ -0,0 +1,142 @@
1
+ // src/openrouter.ts
2
+ function isOpenRouterProvider(provider) {
3
+ const baseUrl = (provider.api_base_url || "").toLowerCase();
4
+ return baseUrl.includes("openrouter.ai");
5
+ }
6
+ var OPENROUTER_APP_HEADERS = {
7
+ "HTTP-Referer": "https://omnicross.dev",
8
+ "X-Title": "omnicross"
9
+ };
10
+
11
+ // src/completion/url-builder.ts
12
+ import { resolveProviderEndpoint as resolveProviderEndpointShared } from "@omnicross/contracts/endpoint-resolver";
13
+ function resolveApiFormat(provider) {
14
+ if (provider.apiFormat) {
15
+ return provider.apiFormat;
16
+ }
17
+ if (provider.chatApiFormat) {
18
+ return provider.chatApiFormat;
19
+ }
20
+ if (provider.apiType === "claudecode" || provider.apiType === "anthropic") {
21
+ return "anthropic";
22
+ }
23
+ if (provider.apiType === "google") {
24
+ return "google";
25
+ }
26
+ return "openai";
27
+ }
28
+
29
+ // src/completion/header-builder.ts
30
+ function getProviderHeaders(provider, apiKey) {
31
+ const format = resolveApiFormat(provider);
32
+ let headers;
33
+ switch (format) {
34
+ case "anthropic":
35
+ headers = {
36
+ "Content-Type": "application/json",
37
+ "x-api-key": apiKey,
38
+ "anthropic-version": "2025-01-10"
39
+ // Required for extended thinking feature
40
+ };
41
+ break;
42
+ case "google":
43
+ headers = {
44
+ "Content-Type": "application/json",
45
+ "x-goog-api-key": apiKey
46
+ };
47
+ break;
48
+ case "azure-openai":
49
+ headers = {
50
+ "Content-Type": "application/json",
51
+ "api-key": apiKey
52
+ };
53
+ break;
54
+ case "openai":
55
+ case "openai-response":
56
+ default:
57
+ headers = {
58
+ "Content-Type": "application/json",
59
+ "Authorization": `Bearer ${apiKey}`
60
+ };
61
+ break;
62
+ }
63
+ if (isOpenRouterProvider(provider)) {
64
+ return { ...headers, ...OPENROUTER_APP_HEADERS };
65
+ }
66
+ return headers;
67
+ }
68
+
69
+ // src/pipeline/LlmConfigProviderAuth.ts
70
+ function isReportableStatus(status) {
71
+ return status === 429 || status === 529 || status === 401 || status === 403;
72
+ }
73
+ var LlmConfigProviderAuth = class {
74
+ provider;
75
+ apiKeyPool;
76
+ providerId;
77
+ sessionId;
78
+ /**
79
+ * The current resolved key. Mutable so a Phase-3 caller can read the
80
+ * rotated key after `onResult`; this phase it is only set at construction
81
+ * and updated inside `onResult` (mirroring the inline re-point in
82
+ * `callWithPoolReporting`).
83
+ */
84
+ apiKey;
85
+ constructor(opts) {
86
+ this.provider = opts.provider;
87
+ this.apiKey = opts.apiKey;
88
+ this.apiKeyPool = opts.apiKeyPool ?? null;
89
+ this.providerId = opts.providerId;
90
+ this.sessionId = opts.sessionId;
91
+ }
92
+ /**
93
+ * Merge the provider auth headers (and content-type / OpenRouter app
94
+ * headers) into `headers`, exactly as a direct `getProviderHeaders` call
95
+ * would produce them. `hints` are accepted for contract symmetry but the
96
+ * provider-key path does not vary headers by URL/model.
97
+ */
98
+ applyHeaders(headers, _hints) {
99
+ const authHeaders = getProviderHeaders(this.provider, this.apiKey);
100
+ for (const [k, v] of Object.entries(authHeaders)) {
101
+ headers[k] = v;
102
+ }
103
+ }
104
+ /**
105
+ * React to the final HTTP status — the pool-rotation seam (design D5).
106
+ *
107
+ * Reproduces `callWithPoolReporting`'s reportable + success branches:
108
+ * - reportable status (429/529/401/403) on a pool-backed request →
109
+ * `reportError(providerId, sessionId, status)`; when it hands back a
110
+ * `newKey` the session was re-bound, so we adopt it (`this.apiKey`) and
111
+ * return `{ rebound: true, newKey }`. When no key is available it returns
112
+ * `{ rebound: false }` (the session is still cooled/disabled by the report).
113
+ * - success / any 2xx → `reportSuccess(sessionId)`; `{ rebound: false }`.
114
+ * - non-reportable, non-success, or non-pool request → no-op
115
+ * `{ rebound: false }`.
116
+ *
117
+ * NOTE: no caller invokes this in Phase 2; it is unit-tested in isolation.
118
+ */
119
+ async onResult(status) {
120
+ const pool = this.apiKeyPool;
121
+ const providerId = this.providerId;
122
+ const sessionId = this.sessionId;
123
+ if (!pool || !providerId || !sessionId) {
124
+ return { rebound: false };
125
+ }
126
+ if (isReportableStatus(status)) {
127
+ const newKey = await pool.reportError(providerId, sessionId, status);
128
+ if (newKey) {
129
+ this.apiKey = newKey;
130
+ return { rebound: true, newKey };
131
+ }
132
+ return { rebound: false };
133
+ }
134
+ if (status !== null && status >= 200 && status < 300) {
135
+ pool.reportSuccess(sessionId);
136
+ }
137
+ return { rebound: false };
138
+ }
139
+ };
140
+ export {
141
+ LlmConfigProviderAuth
142
+ };
@@ -1,3 +1,165 @@
1
- import '@omnicross/contracts/subscription-types';
2
- export { S as SubscriptionAuthProfile, a as SubscriptionAuthSource, b as SubscriptionRequestSummary, s as stripAuthHeaders } from '../SubscriptionAuthSource-Cr4fVEYY.cjs';
3
- import './SubscriptionAuthStrategy.cjs';
1
+ import { OpenCodeGoTokenConfig, OpenCodeGoScenario, OpenCodeGoModelEntry } from '@omnicross/contracts/subscription-types';
2
+ import { AuthSource, AuthApplyHints } from './AuthSource.cjs';
3
+ import { AuthStrategy } from './SubscriptionAuthStrategy.cjs';
4
+
5
+ /**
6
+ * SubscriptionAuthSource — `AuthSource` wrapping a subscription `AuthStrategy`.
7
+ *
8
+ * Phase 2 of the `provider-request-pipeline` OpenSpec change (design D3, task 4.3).
9
+ *
10
+ * Re-expresses the subscription auth used by `SubscriptionDispatcher` behind
11
+ * the unified `AuthSource` contract, delegating to the existing
12
+ * `AuthStrategy` so the OAuth refresh / token formatting logic is NOT
13
+ * rewritten:
14
+ *
15
+ * - `applyHeaders` → `stripAuthHeaders(headers)` then
16
+ * `authStrategy.applyHeaders(headers, { upstreamUrl, resolvedModel })`,
17
+ * wrapped in the same best-effort try/catch as
18
+ * `SubscriptionDispatcher.applyHeadersWithRetry` (a thrown
19
+ * `applyHeaders` is logged + swallowed, NOT propagated — preserved
20
+ * verbatim).
21
+ * - `onUnauthorized` → `authStrategy.onUnauthorized()`.
22
+ * - `resolveUpstreamUrl` → `profile.resolveUpstreamUrl?.(model)`.
23
+ *
24
+ * IMPORTANT (Phase 2 scope): this WRAPS the strategy + strip behavior but does
25
+ * NOT re-route `SubscriptionDispatcher` through it. The dispatcher's fragile
26
+ * 401-refresh + fallback loop is left UNCHANGED (task 4.5 deferred). This
27
+ * class is unit-tested in isolation only.
28
+ *
29
+ * @module pipeline/SubscriptionAuthSource
30
+ */
31
+
32
+ /**
33
+ * Lightweight summary derived from the inbound request body — consumed by a
34
+ * profile's `modelMapper` (scenario routing). Structural mirror of
35
+ * `provider-proxy/types.ts`'s `SubscriptionRequestSummary`, declared here so
36
+ * `SubscriptionAuthProfile.modelMapper` is type-identical WITHOUT a circular
37
+ * import back into `provider-proxy/types` (which imports THIS module).
38
+ */
39
+ interface SubscriptionRequestSummary {
40
+ messageCount: number;
41
+ estimatedInputTokens: number;
42
+ /**
43
+ * OPTIONAL bounded per-message match-text slice — kept structurally identical
44
+ * to the canonical declaration in `provider-proxy/types.ts` (the two are
45
+ * deliberate mirrors, not one shared import). Consumed only by the OpenCodeGo
46
+ * keyword matcher in `@omnicross/subscriptions`; core writes, never reads it.
47
+ */
48
+ matchText?: string[];
49
+ }
50
+ /**
51
+ * The subset of a `SubscriptionDispatchProfile` the subscription paths need.
52
+ * Kept structural (not the full profile type) so the wrapper does not pull in
53
+ * the whole registry surface. The full `SubscriptionDispatchProfile` (which IS
54
+ * what gets passed here) satisfies this shape; the optional `mode` + `modelMapper`
55
+ * are read by the built-in `/v1/messages` subscription path (RT2.1) to decide the
56
+ * verbatim-vs-transformer shape and to apply opencodego scenario routing.
57
+ */
58
+ interface SubscriptionAuthProfile {
59
+ readonly authStrategy: AuthStrategy;
60
+ /** Per-model upstream URL resolver (transformer profiles). Optional for
61
+ * pass-through profiles that hard-code their endpoint upstream. The OPTIONAL
62
+ * 2nd `config` arg (opencodego `baseUrl` override, D1) is additive — existing
63
+ * one-arg callers compile unchanged; mirrors the full
64
+ * `SubscriptionDispatchProfile.resolveUpstreamUrl` so the registry profile
65
+ * stays assignable. */
66
+ readonly resolveUpstreamUrl?: (resolvedModel: string, config?: OpenCodeGoTokenConfig) => string;
67
+ /**
68
+ * Names of provider-level transformers (registered in `TransformerService`)
69
+ * to run on the subscription chain — re-encode Unified → the upstream's wire.
70
+ * The full `SubscriptionDispatchProfile` (which IS what gets passed here)
71
+ * carries these; exposing them on the narrow structural type lets the
72
+ * Responses ingress build the profile's REAL chain (cross-vendor route-to,
73
+ * task #29) instead of hard-coding `['openai-response']`. Absent/empty →
74
+ * the ingress falls back to its endpoint transformer (codex byte-identity).
75
+ */
76
+ readonly providerTransformerNames?: readonly string[];
77
+ /** Names of model-specific transformers — usually empty. See above. */
78
+ readonly modelTransformerNames?: readonly string[];
79
+ /**
80
+ * OPTIONAL shape-aware provider transformer-name resolver (opencodego zen).
81
+ * Type-identical to `SubscriptionDispatchProfile.resolveProviderTransformerNames`
82
+ * so the registry profile stays assignable. The built-in `/v1/messages`
83
+ * subscription path (Phase 3) consults it via
84
+ * `profile.resolveProviderTransformerNames?.(model, route.subscriptionConfig)`
85
+ * to pick the right zen chain per resolved shape. `config` is `unknown` (core
86
+ * opaque-config discipline — no `@omnicross/subscriptions` import). When ABSENT
87
+ * the path reads the static `providerTransformerNames` exactly as today (codex
88
+ * byte-identity).
89
+ */
90
+ readonly resolveProviderTransformerNames?: (model: string, config?: unknown) => readonly string[];
91
+ /**
92
+ * Pass-through (claude) vs transformer (codex / opencodego / gemini). The
93
+ * built-in `/v1/messages` subscription path (RT2.1) reads this for its
94
+ * core-local same-format signal (pass-through ⇒ always verbatim relay).
95
+ * Optional on the narrow type — partial profiles built by other route-minting
96
+ * sites may omit it.
97
+ */
98
+ readonly mode?: 'pass-through' | 'transformer';
99
+ /**
100
+ * Optional model placeholder rewriter — only set for OpenCodeGo. Type-identical
101
+ * to `SubscriptionDispatchProfile.modelMapper` so the registry profile stays
102
+ * assignable. Applied by the built-in `/v1/messages` subscription path BEFORE
103
+ * resolving the upstream URL (so scenario-based shape routing picks the right
104
+ * Anthropic-shape vs OpenAI-shape upstream).
105
+ */
106
+ readonly modelMapper?: (sdkModel: string, summary: SubscriptionRequestSummary, config: OpenCodeGoTokenConfig | undefined) => {
107
+ resolvedModel: string;
108
+ scenario: OpenCodeGoScenario;
109
+ };
110
+ /**
111
+ * Optional fallback resolver — only set for OpenCodeGo. Type-identical to
112
+ * `SubscriptionDispatchProfile.nextFallback` so the registry profile stays
113
+ * assignable. Read by the built-in `/v1/messages` fallback loop (D6b) to pick
114
+ * the next model after an unrecoverable upstream failure; returns `null` when
115
+ * exhausted (claude / codex / gemini omit it → no fallback attempted).
116
+ */
117
+ readonly nextFallback?: (scenario: OpenCodeGoScenario, attempted: readonly string[], config: OpenCodeGoTokenConfig | undefined) => OpenCodeGoModelEntry | null;
118
+ /**
119
+ * Optional circuit-breaker admission gate for the PRIMARY (mapped) model (D5
120
+ * primary-gating). Type-identical to `SubscriptionDispatchProfile.allowModel`.
121
+ * Only OpenCodeGo sets it; the core `/v1/messages` loop consults it for the
122
+ * primary before its first attempt and jumps to the first admitting
123
+ * `nextFallback` candidate when the primary's circuit is open. Absent ⇒ the
124
+ * primary is always admitted (claude / codex / gemini — no breaker).
125
+ */
126
+ readonly allowModel?: (modelId: string) => boolean;
127
+ /**
128
+ * Optional record-outcome callback (D5 record seam). Type-identical to
129
+ * `SubscriptionDispatchProfile.recordModelOutcome`. The core `/v1/messages`
130
+ * loop calls `profile.recordModelOutcome?.(model, ok)` THROUGH this optional
131
+ * field after each attempt, so `@omnicross/core` gains NO import of
132
+ * `@omnicross/subscriptions` (the cross-layer litmus stays 0 — exactly the
133
+ * `nextFallback` precedent). `ok: true` on `2xx`; `ok: false` on
134
+ * thrown/`5xx`/`429`; a non-429 `4xx` is NEUTRAL (the loop does NOT call it).
135
+ * Absent for claude / codex / gemini ⇒ no-op.
136
+ */
137
+ readonly recordModelOutcome?: (modelId: string, ok: boolean) => void;
138
+ }
139
+ /**
140
+ * Drop auth headers the transformer chain may have set so the `AuthStrategy`
141
+ * is the single source of truth for outbound authentication. Byte-identical
142
+ * to `SubscriptionDispatcher.stripAuthHeaders`.
143
+ */
144
+ declare function stripAuthHeaders(headers: Record<string, string>): void;
145
+ declare class SubscriptionAuthSource implements AuthSource {
146
+ private readonly profile;
147
+ constructor(profile: SubscriptionAuthProfile);
148
+ /**
149
+ * Strip any transformer-set auth headers, then delegate to the bound
150
+ * strategy. Mirrors `SubscriptionDispatcher`'s
151
+ * `stripAuthHeaders(...)` + `applyHeadersWithRetry(...)` sequence, including
152
+ * the best-effort swallow-and-warn around a throwing `applyHeaders`.
153
+ *
154
+ * The strategy's looser `AuthApplyHints` (optional `upstreamUrl` /
155
+ * `resolvedModel`) is fed from the pipeline's required `{ upstreamUrl,
156
+ * model }` at the boundary.
157
+ */
158
+ applyHeaders(headers: Record<string, string>, hints: AuthApplyHints): Promise<void>;
159
+ /** Delegate the 401-refresh decision to the bound strategy. */
160
+ onUnauthorized(): Promise<boolean>;
161
+ /** Resolve the upstream URL from the profile, when it provides one. */
162
+ resolveUpstreamUrl(model: string): string | undefined;
163
+ }
164
+
165
+ export { type SubscriptionAuthProfile, SubscriptionAuthSource, type SubscriptionRequestSummary, stripAuthHeaders };
@@ -1,3 +1,165 @@
1
- import '@omnicross/contracts/subscription-types';
2
- export { S as SubscriptionAuthProfile, a as SubscriptionAuthSource, b as SubscriptionRequestSummary, s as stripAuthHeaders } from '../SubscriptionAuthSource-D89zmiSS.js';
3
- import './SubscriptionAuthStrategy.js';
1
+ import { OpenCodeGoTokenConfig, OpenCodeGoScenario, OpenCodeGoModelEntry } from '@omnicross/contracts/subscription-types';
2
+ import { AuthSource, AuthApplyHints } from './AuthSource.js';
3
+ import { AuthStrategy } from './SubscriptionAuthStrategy.js';
4
+
5
+ /**
6
+ * SubscriptionAuthSource — `AuthSource` wrapping a subscription `AuthStrategy`.
7
+ *
8
+ * Phase 2 of the `provider-request-pipeline` OpenSpec change (design D3, task 4.3).
9
+ *
10
+ * Re-expresses the subscription auth used by `SubscriptionDispatcher` behind
11
+ * the unified `AuthSource` contract, delegating to the existing
12
+ * `AuthStrategy` so the OAuth refresh / token formatting logic is NOT
13
+ * rewritten:
14
+ *
15
+ * - `applyHeaders` → `stripAuthHeaders(headers)` then
16
+ * `authStrategy.applyHeaders(headers, { upstreamUrl, resolvedModel })`,
17
+ * wrapped in the same best-effort try/catch as
18
+ * `SubscriptionDispatcher.applyHeadersWithRetry` (a thrown
19
+ * `applyHeaders` is logged + swallowed, NOT propagated — preserved
20
+ * verbatim).
21
+ * - `onUnauthorized` → `authStrategy.onUnauthorized()`.
22
+ * - `resolveUpstreamUrl` → `profile.resolveUpstreamUrl?.(model)`.
23
+ *
24
+ * IMPORTANT (Phase 2 scope): this WRAPS the strategy + strip behavior but does
25
+ * NOT re-route `SubscriptionDispatcher` through it. The dispatcher's fragile
26
+ * 401-refresh + fallback loop is left UNCHANGED (task 4.5 deferred). This
27
+ * class is unit-tested in isolation only.
28
+ *
29
+ * @module pipeline/SubscriptionAuthSource
30
+ */
31
+
32
+ /**
33
+ * Lightweight summary derived from the inbound request body — consumed by a
34
+ * profile's `modelMapper` (scenario routing). Structural mirror of
35
+ * `provider-proxy/types.ts`'s `SubscriptionRequestSummary`, declared here so
36
+ * `SubscriptionAuthProfile.modelMapper` is type-identical WITHOUT a circular
37
+ * import back into `provider-proxy/types` (which imports THIS module).
38
+ */
39
+ interface SubscriptionRequestSummary {
40
+ messageCount: number;
41
+ estimatedInputTokens: number;
42
+ /**
43
+ * OPTIONAL bounded per-message match-text slice — kept structurally identical
44
+ * to the canonical declaration in `provider-proxy/types.ts` (the two are
45
+ * deliberate mirrors, not one shared import). Consumed only by the OpenCodeGo
46
+ * keyword matcher in `@omnicross/subscriptions`; core writes, never reads it.
47
+ */
48
+ matchText?: string[];
49
+ }
50
+ /**
51
+ * The subset of a `SubscriptionDispatchProfile` the subscription paths need.
52
+ * Kept structural (not the full profile type) so the wrapper does not pull in
53
+ * the whole registry surface. The full `SubscriptionDispatchProfile` (which IS
54
+ * what gets passed here) satisfies this shape; the optional `mode` + `modelMapper`
55
+ * are read by the built-in `/v1/messages` subscription path (RT2.1) to decide the
56
+ * verbatim-vs-transformer shape and to apply opencodego scenario routing.
57
+ */
58
+ interface SubscriptionAuthProfile {
59
+ readonly authStrategy: AuthStrategy;
60
+ /** Per-model upstream URL resolver (transformer profiles). Optional for
61
+ * pass-through profiles that hard-code their endpoint upstream. The OPTIONAL
62
+ * 2nd `config` arg (opencodego `baseUrl` override, D1) is additive — existing
63
+ * one-arg callers compile unchanged; mirrors the full
64
+ * `SubscriptionDispatchProfile.resolveUpstreamUrl` so the registry profile
65
+ * stays assignable. */
66
+ readonly resolveUpstreamUrl?: (resolvedModel: string, config?: OpenCodeGoTokenConfig) => string;
67
+ /**
68
+ * Names of provider-level transformers (registered in `TransformerService`)
69
+ * to run on the subscription chain — re-encode Unified → the upstream's wire.
70
+ * The full `SubscriptionDispatchProfile` (which IS what gets passed here)
71
+ * carries these; exposing them on the narrow structural type lets the
72
+ * Responses ingress build the profile's REAL chain (cross-vendor route-to,
73
+ * task #29) instead of hard-coding `['openai-response']`. Absent/empty →
74
+ * the ingress falls back to its endpoint transformer (codex byte-identity).
75
+ */
76
+ readonly providerTransformerNames?: readonly string[];
77
+ /** Names of model-specific transformers — usually empty. See above. */
78
+ readonly modelTransformerNames?: readonly string[];
79
+ /**
80
+ * OPTIONAL shape-aware provider transformer-name resolver (opencodego zen).
81
+ * Type-identical to `SubscriptionDispatchProfile.resolveProviderTransformerNames`
82
+ * so the registry profile stays assignable. The built-in `/v1/messages`
83
+ * subscription path (Phase 3) consults it via
84
+ * `profile.resolveProviderTransformerNames?.(model, route.subscriptionConfig)`
85
+ * to pick the right zen chain per resolved shape. `config` is `unknown` (core
86
+ * opaque-config discipline — no `@omnicross/subscriptions` import). When ABSENT
87
+ * the path reads the static `providerTransformerNames` exactly as today (codex
88
+ * byte-identity).
89
+ */
90
+ readonly resolveProviderTransformerNames?: (model: string, config?: unknown) => readonly string[];
91
+ /**
92
+ * Pass-through (claude) vs transformer (codex / opencodego / gemini). The
93
+ * built-in `/v1/messages` subscription path (RT2.1) reads this for its
94
+ * core-local same-format signal (pass-through ⇒ always verbatim relay).
95
+ * Optional on the narrow type — partial profiles built by other route-minting
96
+ * sites may omit it.
97
+ */
98
+ readonly mode?: 'pass-through' | 'transformer';
99
+ /**
100
+ * Optional model placeholder rewriter — only set for OpenCodeGo. Type-identical
101
+ * to `SubscriptionDispatchProfile.modelMapper` so the registry profile stays
102
+ * assignable. Applied by the built-in `/v1/messages` subscription path BEFORE
103
+ * resolving the upstream URL (so scenario-based shape routing picks the right
104
+ * Anthropic-shape vs OpenAI-shape upstream).
105
+ */
106
+ readonly modelMapper?: (sdkModel: string, summary: SubscriptionRequestSummary, config: OpenCodeGoTokenConfig | undefined) => {
107
+ resolvedModel: string;
108
+ scenario: OpenCodeGoScenario;
109
+ };
110
+ /**
111
+ * Optional fallback resolver — only set for OpenCodeGo. Type-identical to
112
+ * `SubscriptionDispatchProfile.nextFallback` so the registry profile stays
113
+ * assignable. Read by the built-in `/v1/messages` fallback loop (D6b) to pick
114
+ * the next model after an unrecoverable upstream failure; returns `null` when
115
+ * exhausted (claude / codex / gemini omit it → no fallback attempted).
116
+ */
117
+ readonly nextFallback?: (scenario: OpenCodeGoScenario, attempted: readonly string[], config: OpenCodeGoTokenConfig | undefined) => OpenCodeGoModelEntry | null;
118
+ /**
119
+ * Optional circuit-breaker admission gate for the PRIMARY (mapped) model (D5
120
+ * primary-gating). Type-identical to `SubscriptionDispatchProfile.allowModel`.
121
+ * Only OpenCodeGo sets it; the core `/v1/messages` loop consults it for the
122
+ * primary before its first attempt and jumps to the first admitting
123
+ * `nextFallback` candidate when the primary's circuit is open. Absent ⇒ the
124
+ * primary is always admitted (claude / codex / gemini — no breaker).
125
+ */
126
+ readonly allowModel?: (modelId: string) => boolean;
127
+ /**
128
+ * Optional record-outcome callback (D5 record seam). Type-identical to
129
+ * `SubscriptionDispatchProfile.recordModelOutcome`. The core `/v1/messages`
130
+ * loop calls `profile.recordModelOutcome?.(model, ok)` THROUGH this optional
131
+ * field after each attempt, so `@omnicross/core` gains NO import of
132
+ * `@omnicross/subscriptions` (the cross-layer litmus stays 0 — exactly the
133
+ * `nextFallback` precedent). `ok: true` on `2xx`; `ok: false` on
134
+ * thrown/`5xx`/`429`; a non-429 `4xx` is NEUTRAL (the loop does NOT call it).
135
+ * Absent for claude / codex / gemini ⇒ no-op.
136
+ */
137
+ readonly recordModelOutcome?: (modelId: string, ok: boolean) => void;
138
+ }
139
+ /**
140
+ * Drop auth headers the transformer chain may have set so the `AuthStrategy`
141
+ * is the single source of truth for outbound authentication. Byte-identical
142
+ * to `SubscriptionDispatcher.stripAuthHeaders`.
143
+ */
144
+ declare function stripAuthHeaders(headers: Record<string, string>): void;
145
+ declare class SubscriptionAuthSource implements AuthSource {
146
+ private readonly profile;
147
+ constructor(profile: SubscriptionAuthProfile);
148
+ /**
149
+ * Strip any transformer-set auth headers, then delegate to the bound
150
+ * strategy. Mirrors `SubscriptionDispatcher`'s
151
+ * `stripAuthHeaders(...)` + `applyHeadersWithRetry(...)` sequence, including
152
+ * the best-effort swallow-and-warn around a throwing `applyHeaders`.
153
+ *
154
+ * The strategy's looser `AuthApplyHints` (optional `upstreamUrl` /
155
+ * `resolvedModel`) is fed from the pipeline's required `{ upstreamUrl,
156
+ * model }` at the boundary.
157
+ */
158
+ applyHeaders(headers: Record<string, string>, hints: AuthApplyHints): Promise<void>;
159
+ /** Delegate the 401-refresh decision to the bound strategy. */
160
+ onUnauthorized(): Promise<boolean>;
161
+ /** Resolve the upstream URL from the profile, when it provides one. */
162
+ resolveUpstreamUrl(model: string): string | undefined;
163
+ }
164
+
165
+ export { type SubscriptionAuthProfile, SubscriptionAuthSource, type SubscriptionRequestSummary, stripAuthHeaders };