@gajae-code/ai 0.15.5 → 0.16.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.
Files changed (88) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/types/adapter-internals/aws-region.d.ts +7 -0
  3. package/dist/types/auth-broker/client.d.ts +6 -2
  4. package/dist/types/auth-broker/remote-store.d.ts +14 -2
  5. package/dist/types/auth-broker/types.d.ts +6 -0
  6. package/dist/types/auth-broker/wire-schemas.d.ts +19 -0
  7. package/dist/types/auth-gateway/server.d.ts +39 -5
  8. package/dist/types/auth-gateway/types.d.ts +16 -2
  9. package/dist/types/auth-storage.d.ts +92 -24
  10. package/dist/types/core.d.ts +1 -0
  11. package/dist/types/index.d.ts +1 -0
  12. package/dist/types/provider-models/openai-compat.d.ts +1 -0
  13. package/dist/types/providers/anthropic.d.ts +1 -1
  14. package/dist/types/providers/google-gemini-headers.d.ts +1 -1
  15. package/dist/types/providers/openai-codex-responses.d.ts +6 -0
  16. package/dist/types/providers/register-builtins.d.ts +12 -12
  17. package/dist/types/stream.d.ts +2 -1
  18. package/dist/types/types.d.ts +22 -2
  19. package/dist/types/utils/oauth/api-key-login.d.ts +4 -1
  20. package/dist/types/utils/oauth/api-key-validation.d.ts +12 -6
  21. package/dist/types/utils/oauth/commandcode.d.ts +1 -0
  22. package/dist/types/utils/oauth/types.d.ts +1 -1
  23. package/dist/types/utils/retry.d.ts +2 -0
  24. package/dist/types/utils/schema/normalize.d.ts +0 -5
  25. package/dist/types/utils/sqlite-errors.d.ts +4 -0
  26. package/package.json +3 -3
  27. package/src/adapter-internals/aws-region.d.ts +7 -0
  28. package/src/adapter-internals/aws-region.ts +14 -0
  29. package/src/auth-broker/client.ts +41 -13
  30. package/src/auth-broker/redact.ts +25 -1
  31. package/src/auth-broker/remote-store.ts +374 -115
  32. package/src/auth-broker/server.ts +131 -91
  33. package/src/auth-broker/types.ts +6 -0
  34. package/src/auth-broker/wire-schemas.ts +6 -0
  35. package/src/auth-gateway/server.ts +447 -79
  36. package/src/auth-gateway/types.ts +28 -2
  37. package/src/auth-storage.ts +672 -168
  38. package/src/cli.ts +1 -0
  39. package/src/core.ts +1 -0
  40. package/src/index.ts +1 -0
  41. package/src/model-thinking.ts +8 -0
  42. package/src/models.json +1224 -3
  43. package/src/provider-models/descriptors.ts +3 -1
  44. package/src/provider-models/openai-compat.ts +102 -1
  45. package/src/providers/amazon-bedrock.ts +5 -1
  46. package/src/providers/anthropic.d.ts +1 -1
  47. package/src/providers/anthropic.ts +8 -2
  48. package/src/providers/aws-credentials.ts +6 -0
  49. package/src/providers/azure-openai-responses.ts +4 -1
  50. package/src/providers/cursor.ts +256 -101
  51. package/src/providers/gitlab-duo.ts +18 -1
  52. package/src/providers/google-gemini-cli.ts +3 -0
  53. package/src/providers/google-gemini-headers.d.ts +1 -1
  54. package/src/providers/google-gemini-headers.ts +1 -1
  55. package/src/providers/google-shared.ts +3 -0
  56. package/src/providers/kiro-api-key.ts +33 -8
  57. package/src/providers/kiro-codewhisperer.ts +28 -9
  58. package/src/providers/ollama.ts +3 -0
  59. package/src/providers/openai-codex-responses.d.ts +6 -0
  60. package/src/providers/openai-codex-responses.ts +37 -8
  61. package/src/providers/openai-completions.ts +11 -1
  62. package/src/providers/openai-responses.ts +10 -1
  63. package/src/providers/pi-native-client.ts +25 -1
  64. package/src/providers/pi-native-server.ts +24 -0
  65. package/src/providers/register-builtins.d.ts +12 -12
  66. package/src/providers/register-builtins.ts +16 -3
  67. package/src/stream.d.ts +2 -1
  68. package/src/stream.ts +175 -67
  69. package/src/types.d.ts +22 -2
  70. package/src/types.ts +27 -1
  71. package/src/utils/oauth/api-key-login.ts +13 -2
  72. package/src/utils/oauth/api-key-validation.ts +242 -41
  73. package/src/utils/oauth/commandcode.ts +17 -0
  74. package/src/utils/oauth/index.ts +20 -5
  75. package/src/utils/oauth/kiro.ts +91 -22
  76. package/src/utils/oauth/types.d.ts +1 -1
  77. package/src/utils/oauth/types.ts +1 -0
  78. package/src/utils/retry.d.ts +2 -0
  79. package/src/utils/retry.ts +15 -2
  80. package/src/utils/schema/dereference.ts +169 -49
  81. package/src/utils/schema/draft.ts +46 -23
  82. package/src/utils/schema/normalize.d.ts +0 -5
  83. package/src/utils/schema/normalize.ts +396 -119
  84. package/src/utils/schema/types.ts +3 -1
  85. package/src/utils/schema/zod-decontaminate.ts +83 -29
  86. package/src/utils/sqlite-errors.d.ts +4 -0
  87. package/src/utils/sqlite-errors.ts +13 -0
  88. package/src/utils/tool-choice-capability.ts +2 -3
@@ -14,6 +14,7 @@ import {
14
14
  bizrouterModelManagerOptions,
15
15
  cerebrasModelManagerOptions,
16
16
  cloudflareAiGatewayModelManagerOptions,
17
+ commandCodeModelManagerOptions,
17
18
  deepinfraModelManagerOptions,
18
19
  deepseekModelManagerOptions,
19
20
  firepassModelManagerOptions,
@@ -203,6 +204,7 @@ export const PROVIDER_DESCRIPTORS: readonly ProviderDescriptor[] = [
203
204
  ),
204
205
  descriptor("opencode-zen", "claude-sonnet-4-6", config => opencodeZenModelManagerOptions(config)),
205
206
  descriptor("opencode-go", "kimi-k2.5", config => opencodeGoModelManagerOptions(config)),
207
+ descriptor("commandcode-goat", "zai-org/GLM-5.3", config => commandCodeModelManagerOptions(config)),
206
208
  catalogDescriptor(
207
209
  "openrouter",
208
210
  "openai/gpt-5.4",
@@ -370,7 +372,7 @@ export const PROVIDER_DESCRIPTORS: readonly ProviderDescriptor[] = [
370
372
  config => cursorModelManagerOptions(config),
371
373
  catalog("Cursor", ["CURSOR_API_KEY"], { oauthProvider: "cursor" }),
372
374
  ),
373
- descriptor("kiro", "CLAUDE_3_7_SONNET_20250219_V1_0", config => kiroModelManagerOptions(config)),
375
+ descriptor("kiro", "auto", config => kiroModelManagerOptions(config)),
374
376
  ] as const;
375
377
 
376
378
  /** Default model IDs for all known providers, built from descriptors + special providers. */
@@ -832,7 +832,7 @@ export interface OpenCodeModelManagerConfig {
832
832
  }
833
833
 
834
834
  function openCodeModelManagerOptions(
835
- providerId: "opencode-go" | "opencode-zen",
835
+ providerId: "opencode-go" | "opencode-zen" | "commandcode-goat",
836
836
  defaultBaseUrl: string,
837
837
  config?: OpenCodeModelManagerConfig,
838
838
  ): ModelManagerOptions<"openai-completions"> {
@@ -873,6 +873,46 @@ export function opencodeGoModelManagerOptions(
873
873
  return openCodeModelManagerOptions("opencode-go", "https://opencode.ai/zen/go/v1", config);
874
874
  }
875
875
 
876
+ export function commandCodeModelManagerOptions(config?: OpenCodeModelManagerConfig): ModelManagerOptions<Api> {
877
+ const apiKey = config?.apiKey;
878
+ const openAiBaseUrl = config?.baseUrl ?? "https://api.commandcode.ai/provider/v1";
879
+ const anthropicBaseUrl = openAiBaseUrl.replace(/\/v1\/?$/u, "");
880
+ return {
881
+ providerId: "commandcode-goat",
882
+ ...(apiKey && {
883
+ fetchDynamicModels: () =>
884
+ fetchOpenAICompatibleModels<Api>({
885
+ api: "openai-completions",
886
+ provider: "commandcode-goat",
887
+ baseUrl: openAiBaseUrl,
888
+ apiKey,
889
+ mapModel: (_entry, defaults) => {
890
+ const isClaude = /(?:^|\/)claude(?:[\w.-]|$)/iu.test(defaults.id);
891
+ if (isClaude) {
892
+ return {
893
+ ...defaults,
894
+ api: "anthropic-messages",
895
+ baseUrl: anthropicBaseUrl,
896
+ };
897
+ }
898
+ return {
899
+ ...defaults,
900
+ api: "openai-completions",
901
+ compat: {
902
+ ...defaults.compat,
903
+ supportsStore: false,
904
+ supportsDeveloperRole: false,
905
+ supportsReasoningEffort: false,
906
+ maxTokensField: "max_tokens",
907
+ reasoningContentField: "reasoning_content",
908
+ },
909
+ };
910
+ },
911
+ }),
912
+ }),
913
+ };
914
+ }
915
+
876
916
  // ---------------------------------------------------------------------------
877
917
  // 9. Ollama
878
918
  // ---------------------------------------------------------------------------
@@ -2317,11 +2357,15 @@ const OPENCODE_GO_BASE_PATH = "https://opencode.ai/zen/go";
2317
2357
  const OPENCODE_ZEN_API_RESOLUTION = createOpenCodeApiResolution("https://opencode.ai/zen");
2318
2358
  const OPENCODE_GO_CHAT_COMPLETIONS_MODEL_IDS = [
2319
2359
  "deepseek-v4-flash",
2360
+ "deepseek-v4-flash-vision-exp",
2320
2361
  "deepseek-v4-pro",
2321
2362
  "glm-5.1",
2322
2363
  "glm-5.2",
2364
+ "glm-5.3-flash",
2323
2365
  "kimi-k2.6",
2324
2366
  "kimi-k2.7-code",
2367
+ "hy4-preview",
2368
+ "longcat-2.0",
2325
2369
  "mimo-v2.5",
2326
2370
  "mimo-v2.5-pro",
2327
2371
  ] as const;
@@ -2332,6 +2376,7 @@ const OPENCODE_GO_MESSAGES_MODEL_IDS = [
2332
2376
  "qwen3.6-plus",
2333
2377
  "qwen3.7-max",
2334
2378
  "qwen3.7-plus",
2379
+ "qwen3.8-flash",
2335
2380
  ] as const;
2336
2381
  const OPENCODE_GO_API_OVERRIDES: Readonly<Record<string, Api>> = {
2337
2382
  ...Object.fromEntries(OPENCODE_GO_CHAT_COMPLETIONS_MODEL_IDS.map(id => [id, "openai-completions"])),
@@ -2756,6 +2801,62 @@ const OPENCODE_GO_OFFICIAL_MODELS: Readonly<Record<string, OpenCodeGoOfficialMod
2756
2801
  reasoning: true,
2757
2802
  cost: { input: 0.066, output: 0.26, cacheRead: 0.029, cacheWrite: 0 },
2758
2803
  },
2804
+ "deepseek-v4-flash-vision-exp": {
2805
+ name: "DeepSeek V4 Flash Vision Exp",
2806
+ contextWindow: 1_000_000,
2807
+ maxTokens: 384_000,
2808
+ input: ["text", "image"],
2809
+ reasoning: true,
2810
+ cost: { input: 0.22, output: 0.66, cacheRead: 0.007, cacheWrite: 0 },
2811
+ },
2812
+ "glm-5.3-flash": {
2813
+ name: "GLM-5.3-Flash (2x usage)",
2814
+ contextWindow: 1_000_000,
2815
+ maxTokens: 131_072,
2816
+ input: ["text", "image"],
2817
+ reasoning: true,
2818
+ cost: { input: 0.075, output: 0.25, cacheRead: 0.015, cacheWrite: 0 },
2819
+ },
2820
+ "grok-4.6": {
2821
+ name: "Grok 4.6",
2822
+ contextWindow: 500_000,
2823
+ maxTokens: 500_000,
2824
+ input: ["text", "image"],
2825
+ reasoning: true,
2826
+ cost: { input: 2, output: 6, cacheRead: 0.5, cacheWrite: 0 },
2827
+ },
2828
+ "hy4-preview": {
2829
+ name: "Hy4 preview",
2830
+ contextWindow: 1_024_000,
2831
+ maxTokens: 64_000,
2832
+ input: ["text"],
2833
+ reasoning: true,
2834
+ cost: { input: 0.834, output: 2.501, cacheRead: 0.042, cacheWrite: 0 },
2835
+ },
2836
+ "longcat-2.0": {
2837
+ name: "LongCat-2.0",
2838
+ contextWindow: 1_000_000,
2839
+ maxTokens: 131_072,
2840
+ input: ["text"],
2841
+ reasoning: true,
2842
+ cost: { input: 0.3, output: 1.2, cacheRead: 0.006, cacheWrite: 0 },
2843
+ },
2844
+ "muse-spark-1.2-contributor": {
2845
+ name: "Muse Spark 1.2 Contributor",
2846
+ contextWindow: 1_048_576,
2847
+ maxTokens: 131_072,
2848
+ input: ["text", "image"],
2849
+ reasoning: true,
2850
+ cost: { input: 0.1, output: 0.2, cacheRead: 0.002, cacheWrite: 0 },
2851
+ },
2852
+ "qwen3.8-flash": {
2853
+ name: "Qwen3.8 Flash",
2854
+ contextWindow: 1_000_000,
2855
+ maxTokens: 131_072,
2856
+ input: ["text", "image"],
2857
+ reasoning: true,
2858
+ cost: { input: 0.15, output: 0.47, cacheRead: 0.016, cacheWrite: 0.2 },
2859
+ },
2759
2860
  };
2760
2861
 
2761
2862
  function applyOpenCodeGoOfficialMetadata<TApi extends Api>(model: Model<TApi>): Model<TApi> {
@@ -8,6 +8,7 @@
8
8
  */
9
9
 
10
10
  import { $credentialEnv, $env, $flag, extractHttpStatusFromError, fetchWithRetry } from "@gajae-code/utils";
11
+ import { assertAwsRegionLabel } from "../adapter-internals/aws-region";
11
12
  import type { Effort } from "../model-thinking";
12
13
  import {
13
14
  mapEffortToAnthropicAdaptiveEffort,
@@ -202,9 +203,10 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
202
203
 
203
204
  const blocks = output.content as Block[];
204
205
  let rawRequestDump: RawHttpRequestDump | undefined;
205
- const region = options.region || $env.AWS_REGION || $env.AWS_DEFAULT_REGION || "us-east-1";
206
+ const region = options.region ?? $env.AWS_REGION ?? $env.AWS_DEFAULT_REGION ?? "us-east-1";
206
207
 
207
208
  try {
209
+ assertAwsRegionLabel(region);
208
210
  const cacheRetention = resolveCacheRetention(options.cacheRetention);
209
211
  const resolvedToolChoice = resolveToolChoice(model, options.toolChoice);
210
212
  const toolConfig = convertToolConfig(context.tools, resolvedToolChoice.resolvedChoice);
@@ -303,6 +305,7 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
303
305
  method: "POST",
304
306
  headers: await buildRequestHeaders(retryBody),
305
307
  body: retryBody,
308
+ redirect: "error",
306
309
  signal: options.signal,
307
310
  maxAttempts: 1,
308
311
  });
@@ -312,6 +315,7 @@ export const streamBedrock: StreamFunction<"bedrock-converse-stream"> = (
312
315
  method: "POST",
313
316
  headers: requestHeaders,
314
317
  body,
318
+ redirect: "error",
315
319
  signal: options.signal,
316
320
  maxAttempts: resolveRetryBudget(options.requestMaxRetries, 4) + 1,
317
321
  });
@@ -107,7 +107,7 @@ export interface CpaToolAliasRestoreFailure {
107
107
  */
108
108
  export declare function parseCpaToolAliasRestoreFailure(error: unknown): CpaToolAliasRestoreFailure | undefined;
109
109
  export declare function isCpaToolAliasRestoreFailure(error: unknown): boolean;
110
- export declare const claudeCodeVersion = "2.1.219";
110
+ export declare const claudeCodeVersion = "2.1.257";
111
111
  export declare const claudeCodeEntrypoint = "sdk-cli";
112
112
  export declare const claudeToolPrefix: string;
113
113
  export declare const claudeCodeSystemInstruction = "You are a Claude agent, built on Anthropic's Claude Agent SDK.";
@@ -828,7 +828,7 @@ function getCacheControl(
828
828
  }
829
829
 
830
830
  // Stealth mode: Mimic Anthropic Code headers and tool prefixing.
831
- export const claudeCodeVersion = "2.1.219";
831
+ export const claudeCodeVersion = "2.1.257";
832
832
  export const claudeCodeEntrypoint = "sdk-cli";
833
833
  export const claudeToolPrefix: string = "proxy_";
834
834
  export const claudeCodeSystemInstruction = "You are a Claude agent, built on Anthropic's Claude Agent SDK.";
@@ -2143,6 +2143,7 @@ export const streamAnthropic: StreamFunction<"anthropic-messages"> = (
2143
2143
  const idleTimeoutAbortError = new Error("Anthropic stream stalled while waiting for the next event");
2144
2144
  const { requestSignal } = activeAbortTracker;
2145
2145
  setRawRequestDump(params);
2146
+ options?.onStreamCreated?.();
2146
2147
  const anthropicRequest = client.messages.create(
2147
2148
  { ...params, stream: true },
2148
2149
  {
@@ -2616,6 +2617,7 @@ export const streamAnthropic: StreamFunction<"anthropic-messages"> = (
2616
2617
  }
2617
2618
  if (
2618
2619
  !options?.fallbackManaged &&
2620
+ !options?.disableProviderRetries &&
2619
2621
  !disableStrictTools &&
2620
2622
  firstTokenTime === undefined &&
2621
2623
  hasStrictAnthropicTools(params) &&
@@ -2636,6 +2638,7 @@ export const streamAnthropic: StreamFunction<"anthropic-messages"> = (
2636
2638
  !droppedForcedToolChoice &&
2637
2639
  firstTokenTime === undefined &&
2638
2640
  !options?.fallbackManaged &&
2641
+ !options?.disableProviderRetries &&
2639
2642
  isSentForcedAnthropicToolChoice(params.tool_choice) &&
2640
2643
  isForcedToolChoiceUnsupportedError(streamFailure, true)
2641
2644
  ) {
@@ -2667,6 +2670,7 @@ export const streamAnthropic: StreamFunction<"anthropic-messages"> = (
2667
2670
  const maskedProxyRejection = isAnthropicMaskedProxyRejection(streamFailure);
2668
2671
  if (
2669
2672
  !options?.fallbackManaged &&
2673
+ !options?.disableProviderRetries &&
2670
2674
  thinkingReplayRepairScope === "none" &&
2671
2675
  thinkingReplayRepairAttempts < ANTHROPIC_MAX_THINKING_REPAIRS &&
2672
2676
  firstTokenTime === undefined &&
@@ -2804,6 +2808,7 @@ export const streamAnthropic: StreamFunction<"anthropic-messages"> = (
2804
2808
  }
2805
2809
  if (
2806
2810
  !options?.fallbackManaged &&
2811
+ !options?.disableProviderRetries &&
2807
2812
  !dropFastMode &&
2808
2813
  resolveServiceTier(options?.serviceTier, model.provider) === "priority" &&
2809
2814
  firstTokenTime === undefined &&
@@ -2825,6 +2830,7 @@ export const streamAnthropic: StreamFunction<"anthropic-messages"> = (
2825
2830
  }
2826
2831
  if (
2827
2832
  !options?.fallbackManaged &&
2833
+ !options?.disableProviderRetries &&
2828
2834
  generatedCacheBudget > 0 &&
2829
2835
  firstTokenTime === undefined &&
2830
2836
  isAnthropicCacheBreakpointOverflowError(streamFailure)
@@ -2862,7 +2868,7 @@ export const streamAnthropic: StreamFunction<"anthropic-messages"> = (
2862
2868
  // Anthropic and non-CPA proxies are untouched.
2863
2869
  const cpaAliasFailure = parseCpaToolAliasRestoreFailure(streamFailure);
2864
2870
  if (cpaAliasFailure && firstTokenTime === undefined) {
2865
- if (options?.fallbackManaged) {
2871
+ if (options?.fallbackManaged || options?.disableProviderRetries) {
2866
2872
  // The managed fallback controller owns retries: never retry
2867
2873
  // inside the attempt it handed us. Record the corrective
2868
2874
  // steering against this exact turn and surface the raw error;
@@ -22,6 +22,7 @@
22
22
  import * as fs from "node:fs";
23
23
  import * as path from "node:path";
24
24
  import { $env, getTrustedHomeDir, isEnoent, logger } from "@gajae-code/utils";
25
+ import { assertAwsRegionLabel } from "../adapter-internals/aws-region";
25
26
  import {
26
27
  type AwsIniFile,
27
28
  classifyAwsProfileCapability,
@@ -155,6 +156,7 @@ async function readSsoCredentials(
155
156
  }
156
157
  }
157
158
  if (!startUrl || !ssoRegion) return undefined;
159
+ assertAwsRegionLabel(ssoRegion);
158
160
 
159
161
  const token = await loadSsoCachedToken(startUrl, sessionName);
160
162
  if (!token?.accessToken) {
@@ -172,6 +174,7 @@ async function readSsoCredentials(
172
174
  const response = await fetch(url, {
173
175
  method: "GET",
174
176
  headers: { "x-amz-sso_bearer_token": token.accessToken },
177
+ redirect: "error",
175
178
  signal,
176
179
  });
177
180
  if (!response.ok) {
@@ -411,6 +414,7 @@ async function readImdsCredentials(parentSignal: AbortSignal | undefined): Promi
411
414
  const tokenRes = await fetch(`http://${IMDS_HOST}/latest/api/token`, {
412
415
  method: "PUT",
413
416
  headers: { "x-aws-ec2-metadata-token-ttl-seconds": "21600" },
417
+ redirect: "error",
414
418
  signal,
415
419
  });
416
420
  if (!tokenRes.ok) return undefined;
@@ -418,6 +422,7 @@ async function readImdsCredentials(parentSignal: AbortSignal | undefined): Promi
418
422
 
419
423
  const roleRes = await fetch(`http://${IMDS_HOST}/latest/meta-data/iam/security-credentials/`, {
420
424
  headers: { "x-aws-ec2-metadata-token": token },
425
+ redirect: "error",
421
426
  signal,
422
427
  });
423
428
  if (!roleRes.ok) return undefined;
@@ -428,6 +433,7 @@ async function readImdsCredentials(parentSignal: AbortSignal | undefined): Promi
428
433
  `http://${IMDS_HOST}/latest/meta-data/iam/security-credentials/${encodeURIComponent(role)}`,
429
434
  {
430
435
  headers: { "x-aws-ec2-metadata-token": token },
436
+ redirect: "error",
431
437
  signal,
432
438
  },
433
439
  );
@@ -142,11 +142,13 @@ export const streamAzureOpenAIResponses: StreamFunction<"azure-openai-responses"
142
142
  };
143
143
  let openaiStream: Awaited<ReturnType<typeof client.responses.create>>;
144
144
  try {
145
+ options?.onStreamCreated?.();
145
146
  openaiStream = await client.responses.create(params, { signal: requestSignal });
146
147
  } catch (error) {
147
148
  if (
148
149
  !isForcedToolChoiceUnsupportedError(error, isForcedAzureResponsesToolChoice(params.tool_choice)) ||
149
- options?.fallbackManaged
150
+ options?.fallbackManaged ||
151
+ options?.disableProviderRetries
150
152
  ) {
151
153
  throw error;
152
154
  }
@@ -165,6 +167,7 @@ export const streamAzureOpenAIResponses: StreamFunction<"azure-openai-responses"
165
167
  });
166
168
  delete params.tool_choice;
167
169
  rawRequestDump = { ...rawRequestDump, body: params };
170
+ options?.onStreamCreated?.();
168
171
  openaiStream = await client.responses.create(params, { signal: requestSignal });
169
172
  }
170
173
  streamConnected = true;