indusagi 0.13.10 → 0.13.12
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/dist/agent.js +204 -29
- package/dist/ai.js +204 -29
- package/dist/cli.js +92 -9
- package/dist/index.js +186 -21
- package/dist/llmgateway.js +81 -4
- package/dist/mcp.js +94 -12
- package/dist/react-host/jsx-dev-runtime.js +93 -0
- package/dist/react-ink.js +11 -5
- package/dist/runtime.js +81 -4
- package/dist/shell-app.js +92 -9
- package/dist/smithy.js +81 -4
- package/dist/swarm.js +81 -4
- package/dist/types/facade/agent.d.ts +1 -1
- package/dist/types/facade/agent.test.d.ts +1 -0
- package/dist/types/facade/ai.d.ts +1 -1
- package/dist/types/facade/bot/types.d.ts +3 -3
- package/dist/types/facade/mcp.d.ts +1 -1
- package/dist/types/facade/ml/adapters/openai-codex-responses.d.ts +1 -1
- package/dist/types/facade/ml/adapters/openai-codex-responses.test.d.ts +1 -0
- package/dist/types/facade/ml/adapters/openai-responses.d.ts +1 -1
- package/dist/types/facade/ml/adapters/openai-responses.test.d.ts +1 -0
- package/dist/types/facade/ml/adapters/simple-options.d.ts +2 -2
- package/dist/types/facade/ml/auth-store.d.ts +7 -0
- package/dist/types/facade/ml/auth-store.test.d.ts +1 -0
- package/dist/types/facade/ml/models.generated.d.ts +162 -0
- package/dist/types/facade/ml/types.d.ts +14 -1
- package/dist/types/llmgateway/connectors/openai-responses.test.d.ts +1 -0
- package/dist/types/llmgateway/contract/index.d.ts +2 -2
- package/dist/types/llmgateway/contract/model-card.d.ts +14 -0
- package/dist/types/llmgateway/contract/options.d.ts +3 -1
- package/dist/types/react-host/jsx-dev-runtime.d.ts +3 -0
- package/dist/types/react-host/loader.d.ts +1 -0
- package/dist/types/security/private-state.d.ts +3 -0
- package/dist/zoho.js +94 -12
- package/package.json +7 -2
package/dist/agent.js
CHANGED
|
@@ -4694,6 +4694,72 @@ var MODELS = {
|
|
|
4694
4694
|
contextWindow: 1e6,
|
|
4695
4695
|
maxTokens: 128e3
|
|
4696
4696
|
},
|
|
4697
|
+
"gpt-6-astra": {
|
|
4698
|
+
id: "gpt-6-astra",
|
|
4699
|
+
name: "GPT-6 Astra",
|
|
4700
|
+
api: "openai-responses",
|
|
4701
|
+
provider: "openai",
|
|
4702
|
+
baseUrl: "https://api.openai.com/v1",
|
|
4703
|
+
reasoning: true,
|
|
4704
|
+
reasoningEfforts: ["low", "medium", "high", "xhigh", "max"],
|
|
4705
|
+
input: ["text", "image"],
|
|
4706
|
+
cost: {
|
|
4707
|
+
input: 10,
|
|
4708
|
+
output: 50,
|
|
4709
|
+
cacheRead: 1,
|
|
4710
|
+
cacheWrite: 12.5
|
|
4711
|
+
},
|
|
4712
|
+
longContextPricing: {
|
|
4713
|
+
threshold: 272e3,
|
|
4714
|
+
multipliers: {
|
|
4715
|
+
input: 2,
|
|
4716
|
+
output: 1.5,
|
|
4717
|
+
cacheRead: 2,
|
|
4718
|
+
cacheWrite: 2
|
|
4719
|
+
}
|
|
4720
|
+
},
|
|
4721
|
+
contextWindow: 105e4,
|
|
4722
|
+
maxTokens: 128e3
|
|
4723
|
+
},
|
|
4724
|
+
"gpt-6-sol": {
|
|
4725
|
+
id: "gpt-6-sol",
|
|
4726
|
+
name: "GPT-6 Sol",
|
|
4727
|
+
api: "openai-responses",
|
|
4728
|
+
provider: "openai",
|
|
4729
|
+
baseUrl: "https://api.openai.com/v1",
|
|
4730
|
+
reasoning: true,
|
|
4731
|
+
reasoningEfforts: ["high"],
|
|
4732
|
+
input: ["text", "image"],
|
|
4733
|
+
cost: {
|
|
4734
|
+
input: 10,
|
|
4735
|
+
output: 50,
|
|
4736
|
+
cacheRead: 1,
|
|
4737
|
+
cacheWrite: 12.5
|
|
4738
|
+
},
|
|
4739
|
+
longContextPricing: {
|
|
4740
|
+
threshold: 272e3,
|
|
4741
|
+
multipliers: { input: 2, output: 1.5, cacheRead: 2, cacheWrite: 2 }
|
|
4742
|
+
},
|
|
4743
|
+
contextWindow: 105e4,
|
|
4744
|
+
maxTokens: 128e3
|
|
4745
|
+
},
|
|
4746
|
+
"gpt-6-luna": {
|
|
4747
|
+
id: "gpt-6-luna",
|
|
4748
|
+
name: "GPT-6 Luna",
|
|
4749
|
+
api: "openai-responses",
|
|
4750
|
+
provider: "openai",
|
|
4751
|
+
baseUrl: "https://api.openai.com/v1",
|
|
4752
|
+
reasoning: true,
|
|
4753
|
+
reasoningEfforts: ["low", "medium", "high", "xhigh", "max"],
|
|
4754
|
+
input: ["text", "image"],
|
|
4755
|
+
cost: { input: 0.1, output: 0.5, cacheRead: 0.01, cacheWrite: 0.125 },
|
|
4756
|
+
longContextPricing: {
|
|
4757
|
+
threshold: 272e3,
|
|
4758
|
+
multipliers: { input: 2, output: 1.5, cacheRead: 2, cacheWrite: 2 }
|
|
4759
|
+
},
|
|
4760
|
+
contextWindow: 105e4,
|
|
4761
|
+
maxTokens: 128e3
|
|
4762
|
+
},
|
|
4697
4763
|
"gpt-5.6-sol": {
|
|
4698
4764
|
id: "gpt-5.6-sol",
|
|
4699
4765
|
name: "GPT-5.6 Sol",
|
|
@@ -5156,6 +5222,67 @@ var MODELS = {
|
|
|
5156
5222
|
},
|
|
5157
5223
|
contextWindow: 105e4,
|
|
5158
5224
|
maxTokens: 128e3
|
|
5225
|
+
},
|
|
5226
|
+
"gpt-6-astra": {
|
|
5227
|
+
id: "gpt-6-astra",
|
|
5228
|
+
name: "GPT-6 Astra",
|
|
5229
|
+
api: "openai-codex-responses",
|
|
5230
|
+
provider: "openai-codex",
|
|
5231
|
+
baseUrl: "https://chatgpt.com/backend-api",
|
|
5232
|
+
reasoning: true,
|
|
5233
|
+
reasoningEfforts: ["low", "medium", "high", "xhigh", "max"],
|
|
5234
|
+
input: ["text", "image"],
|
|
5235
|
+
cost: {
|
|
5236
|
+
input: 10,
|
|
5237
|
+
output: 50,
|
|
5238
|
+
cacheRead: 1,
|
|
5239
|
+
cacheWrite: 12.5
|
|
5240
|
+
},
|
|
5241
|
+
longContextPricing: {
|
|
5242
|
+
threshold: 272e3,
|
|
5243
|
+
multipliers: { input: 2, output: 1.5, cacheRead: 2, cacheWrite: 2 }
|
|
5244
|
+
},
|
|
5245
|
+
contextWindow: 105e4,
|
|
5246
|
+
maxTokens: 128e3
|
|
5247
|
+
},
|
|
5248
|
+
"gpt-6-sol": {
|
|
5249
|
+
id: "gpt-6-sol",
|
|
5250
|
+
name: "GPT-6 Sol",
|
|
5251
|
+
api: "openai-codex-responses",
|
|
5252
|
+
provider: "openai-codex",
|
|
5253
|
+
baseUrl: "https://chatgpt.com/backend-api",
|
|
5254
|
+
reasoning: true,
|
|
5255
|
+
reasoningEfforts: ["high"],
|
|
5256
|
+
input: ["text", "image"],
|
|
5257
|
+
cost: {
|
|
5258
|
+
input: 10,
|
|
5259
|
+
output: 50,
|
|
5260
|
+
cacheRead: 1,
|
|
5261
|
+
cacheWrite: 12.5
|
|
5262
|
+
},
|
|
5263
|
+
longContextPricing: {
|
|
5264
|
+
threshold: 272e3,
|
|
5265
|
+
multipliers: { input: 2, output: 1.5, cacheRead: 2, cacheWrite: 2 }
|
|
5266
|
+
},
|
|
5267
|
+
contextWindow: 105e4,
|
|
5268
|
+
maxTokens: 128e3
|
|
5269
|
+
},
|
|
5270
|
+
"gpt-6-luna": {
|
|
5271
|
+
id: "gpt-6-luna",
|
|
5272
|
+
name: "GPT-6 Luna",
|
|
5273
|
+
api: "openai-codex-responses",
|
|
5274
|
+
provider: "openai-codex",
|
|
5275
|
+
baseUrl: "https://chatgpt.com/backend-api",
|
|
5276
|
+
reasoning: true,
|
|
5277
|
+
reasoningEfforts: ["low", "medium", "high", "xhigh", "max"],
|
|
5278
|
+
input: ["text", "image"],
|
|
5279
|
+
cost: { input: 0.1, output: 0.5, cacheRead: 0.01, cacheWrite: 0.125 },
|
|
5280
|
+
longContextPricing: {
|
|
5281
|
+
threshold: 272e3,
|
|
5282
|
+
multipliers: { input: 2, output: 1.5, cacheRead: 2, cacheWrite: 2 }
|
|
5283
|
+
},
|
|
5284
|
+
contextWindow: 105e4,
|
|
5285
|
+
maxTokens: 128e3
|
|
5159
5286
|
}
|
|
5160
5287
|
},
|
|
5161
5288
|
"opencode": {
|
|
@@ -12668,9 +12795,9 @@ function getModels(provider) {
|
|
|
12668
12795
|
function calculateCost(model, usage) {
|
|
12669
12796
|
return modelRegistry.calculateCost(model, usage);
|
|
12670
12797
|
}
|
|
12671
|
-
var XHIGH_MODEL_IDS = /* @__PURE__ */ new Set(["gpt-5.1-codex-max", "gpt-5.2", "gpt-5.2-codex"]);
|
|
12798
|
+
var XHIGH_MODEL_IDS = /* @__PURE__ */ new Set(["gpt-5.1-codex-max", "gpt-5.2", "gpt-5.2-codex", "gpt-6-astra"]);
|
|
12672
12799
|
function supportsXhigh(model) {
|
|
12673
|
-
return XHIGH_MODEL_IDS.has(model.id);
|
|
12800
|
+
return model.reasoningEfforts?.includes("xhigh") ?? XHIGH_MODEL_IDS.has(model.id);
|
|
12674
12801
|
}
|
|
12675
12802
|
|
|
12676
12803
|
// src/facade/ml/types.ts
|
|
@@ -13358,12 +13485,12 @@ function buildBaseOptions(model, options, apiKey) {
|
|
|
13358
13485
|
return base;
|
|
13359
13486
|
}
|
|
13360
13487
|
function clampReasoning(effort) {
|
|
13361
|
-
if (effort === "xhigh") return "high";
|
|
13488
|
+
if (effort === "xhigh" || effort === "max") return "high";
|
|
13362
13489
|
return effort;
|
|
13363
13490
|
}
|
|
13364
13491
|
function mapThinkingLevel(level, provider = "clamp-xhigh") {
|
|
13365
13492
|
if (!level) return void 0;
|
|
13366
|
-
if (provider === "supports-xhigh") return level;
|
|
13493
|
+
if (provider === "supports-xhigh") return level === "max" ? "high" : level;
|
|
13367
13494
|
return clampReasoning(level);
|
|
13368
13495
|
}
|
|
13369
13496
|
var RESERVED_ANSWER_TOKENS = 1024;
|
|
@@ -13375,8 +13502,10 @@ var REASONING_BUDGET_DEFAULTS = {
|
|
|
13375
13502
|
// 2Ki
|
|
13376
13503
|
medium: BUDGET_UNIT * 8,
|
|
13377
13504
|
// 8Ki
|
|
13378
|
-
high: BUDGET_UNIT * 16
|
|
13505
|
+
high: BUDGET_UNIT * 16,
|
|
13379
13506
|
// 16Ki
|
|
13507
|
+
max: BUDGET_UNIT * 16
|
|
13508
|
+
// clamped to high for generic token-budget providers
|
|
13380
13509
|
};
|
|
13381
13510
|
function adjustMaxTokensForThinking(baseMaxTokens, modelMaxTokens, reasoningLevel, customBudgets) {
|
|
13382
13511
|
const budgets = { ...REASONING_BUDGET_DEFAULTS, ...customBudgets };
|
|
@@ -16575,7 +16704,7 @@ var OpenAIResponsesParamBuilder = class {
|
|
|
16575
16704
|
if (this.options?.maxTokens) {
|
|
16576
16705
|
params.max_output_tokens = this.options.maxTokens;
|
|
16577
16706
|
}
|
|
16578
|
-
if (this.options?.temperature !== void 0) {
|
|
16707
|
+
if (!(/* @__PURE__ */ new Set(["gpt-6-astra", "gpt-6-sol", "gpt-6-luna"])).has(this.model.id) && this.options?.temperature !== void 0) {
|
|
16579
16708
|
params.temperature = this.options.temperature;
|
|
16580
16709
|
}
|
|
16581
16710
|
if (this.options?.serviceTier !== void 0) {
|
|
@@ -16629,7 +16758,11 @@ var streamSimpleOpenAIResponses = (model, context, options) => {
|
|
|
16629
16758
|
throw new Error(`No API key for provider: ${model.provider}`);
|
|
16630
16759
|
}
|
|
16631
16760
|
const base = buildBaseOptions(model, options, apiKey);
|
|
16632
|
-
const
|
|
16761
|
+
const requestedEffort = options?.reasoning;
|
|
16762
|
+
const reasoningEffort = model.reasoningEfforts ? requestedEffort !== void 0 && requestedEffort !== "minimal" && model.reasoningEfforts.includes(requestedEffort) ? requestedEffort : void 0 : mapThinkingLevel(
|
|
16763
|
+
requestedEffort === "max" ? "high" : requestedEffort,
|
|
16764
|
+
supportsXhigh(model) ? "supports-xhigh" : "clamp-xhigh"
|
|
16765
|
+
);
|
|
16633
16766
|
return streamOpenAIResponses(model, context, {
|
|
16634
16767
|
...base,
|
|
16635
16768
|
reasoningEffort
|
|
@@ -16664,8 +16797,8 @@ if (typeof process !== "undefined" && (process.versions?.node || process.version
|
|
|
16664
16797
|
}
|
|
16665
16798
|
var CODEX_URL = "https://chatgpt.com/backend-api/codex/responses";
|
|
16666
16799
|
var JWT_CLAIM_PATH = "https://api.openai.com/auth";
|
|
16667
|
-
var MAX_RETRIES =
|
|
16668
|
-
var
|
|
16800
|
+
var MAX_RETRIES = 4;
|
|
16801
|
+
var RETRY_DELAY_MS = 1e4;
|
|
16669
16802
|
var CODEX_TOOL_CALL_PROVIDERS = /* @__PURE__ */ new Set(["openai", "openai-codex", "opencode"]);
|
|
16670
16803
|
var CODEX_RESPONSE_STATUSES = /* @__PURE__ */ new Set([
|
|
16671
16804
|
"completed",
|
|
@@ -16679,21 +16812,29 @@ var TRANSIENT_ERROR_PATTERNS = [
|
|
|
16679
16812
|
/rate.?limit/i,
|
|
16680
16813
|
/overloaded/i,
|
|
16681
16814
|
/service.?unavailable/i,
|
|
16815
|
+
/server.?error/i,
|
|
16816
|
+
/terminated/i,
|
|
16682
16817
|
/upstream.?connect/i,
|
|
16683
16818
|
/connection.?refused/i
|
|
16684
16819
|
];
|
|
16685
16820
|
var RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
16686
16821
|
var CodexRetryExecutor = class _CodexRetryExecutor {
|
|
16822
|
+
static terminalErrorMarker = /* @__PURE__ */ Symbol("codexTerminalError");
|
|
16687
16823
|
static isRetryable(status, errorText) {
|
|
16688
16824
|
if (RETRYABLE_STATUS_CODES.has(status)) {
|
|
16689
16825
|
return true;
|
|
16690
16826
|
}
|
|
16691
16827
|
return TRANSIENT_ERROR_PATTERNS.some((pattern) => pattern.test(errorText));
|
|
16692
16828
|
}
|
|
16693
|
-
|
|
16694
|
-
|
|
16695
|
-
|
|
16696
|
-
|
|
16829
|
+
static backoffDelay(_attempt) {
|
|
16830
|
+
return RETRY_DELAY_MS;
|
|
16831
|
+
}
|
|
16832
|
+
static markTerminal(error) {
|
|
16833
|
+
error[_CodexRetryExecutor.terminalErrorMarker] = true;
|
|
16834
|
+
return error;
|
|
16835
|
+
}
|
|
16836
|
+
static isTerminal(error) {
|
|
16837
|
+
return Boolean(error[_CodexRetryExecutor.terminalErrorMarker]);
|
|
16697
16838
|
}
|
|
16698
16839
|
static sleep(ms, signal) {
|
|
16699
16840
|
return new Promise((resolve5, reject) => {
|
|
@@ -16729,12 +16870,15 @@ var CodexRetryExecutor = class _CodexRetryExecutor {
|
|
|
16729
16870
|
statusText: response.statusText
|
|
16730
16871
|
});
|
|
16731
16872
|
const info = await CodexErrorInterpreter.parse(fakeResponse);
|
|
16732
|
-
throw new Error(info.friendlyMessage || info.message);
|
|
16873
|
+
throw _CodexRetryExecutor.markTerminal(new Error(info.friendlyMessage || info.message));
|
|
16733
16874
|
} catch (error) {
|
|
16734
16875
|
if (error instanceof Error && (error.name === "AbortError" || error.message === "Request was aborted")) {
|
|
16735
16876
|
throw new Error("Request was aborted");
|
|
16736
16877
|
}
|
|
16737
16878
|
lastError = error instanceof Error ? error : new Error(String(error));
|
|
16879
|
+
if (_CodexRetryExecutor.isTerminal(lastError)) {
|
|
16880
|
+
throw lastError;
|
|
16881
|
+
}
|
|
16738
16882
|
if (attempt < MAX_RETRIES && !lastError.message.includes("usage limit")) {
|
|
16739
16883
|
await _CodexRetryExecutor.sleep(_CodexRetryExecutor.backoffDelay(attempt), options?.signal);
|
|
16740
16884
|
continue;
|
|
@@ -16802,20 +16946,45 @@ var streamOpenAICodexResponses = (model, context, options) => {
|
|
|
16802
16946
|
const requestFactory = new CodexRequestFactory(model, context, options, apiKey);
|
|
16803
16947
|
const { body, bodyJson, headers } = requestFactory.buildPayload();
|
|
16804
16948
|
options?.onPayload?.(body);
|
|
16805
|
-
|
|
16806
|
-
|
|
16807
|
-
|
|
16808
|
-
|
|
16809
|
-
|
|
16810
|
-
|
|
16811
|
-
|
|
16812
|
-
|
|
16813
|
-
|
|
16814
|
-
|
|
16815
|
-
|
|
16949
|
+
let completedOutput;
|
|
16950
|
+
let completedEvents;
|
|
16951
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
16952
|
+
const response = await executeWithCodexRetry(
|
|
16953
|
+
() => fetch(CODEX_URL, {
|
|
16954
|
+
method: "POST",
|
|
16955
|
+
headers,
|
|
16956
|
+
body: bodyJson,
|
|
16957
|
+
signal: options?.signal
|
|
16958
|
+
}),
|
|
16959
|
+
options?.signal
|
|
16960
|
+
);
|
|
16961
|
+
if (!response.body) {
|
|
16962
|
+
throw new Error("No response body");
|
|
16963
|
+
}
|
|
16964
|
+
const attemptOutput = createAssistantMessageOutput(model);
|
|
16965
|
+
const attemptStream = new AssistantMessageEventStream();
|
|
16966
|
+
try {
|
|
16967
|
+
await processStream(response, attemptOutput, attemptStream, model);
|
|
16968
|
+
completedOutput = attemptOutput;
|
|
16969
|
+
completedEvents = [...attemptStream.getHistory()];
|
|
16970
|
+
break;
|
|
16971
|
+
} catch (error) {
|
|
16972
|
+
if (options?.signal?.aborted) {
|
|
16973
|
+
throw new Error("Request was aborted");
|
|
16974
|
+
}
|
|
16975
|
+
const message = error instanceof Error ? error.message : JSON.stringify(error);
|
|
16976
|
+
if (attempt >= MAX_RETRIES || !CodexRetryExecutor.isRetryable(200, message)) {
|
|
16977
|
+
throw error;
|
|
16978
|
+
}
|
|
16979
|
+
await CodexRetryExecutor.sleep(CodexRetryExecutor.backoffDelay(attempt), options?.signal);
|
|
16980
|
+
}
|
|
16981
|
+
}
|
|
16982
|
+
if (!completedOutput || !completedEvents) {
|
|
16983
|
+
throw new Error("Failed after retries");
|
|
16816
16984
|
}
|
|
16985
|
+
Object.assign(output, completedOutput);
|
|
16817
16986
|
events.start();
|
|
16818
|
-
|
|
16987
|
+
for (const event of completedEvents) stream.push(event);
|
|
16819
16988
|
if (options?.signal?.aborted) {
|
|
16820
16989
|
throw new Error("Request was aborted");
|
|
16821
16990
|
}
|
|
@@ -16838,7 +17007,8 @@ var streamSimpleOpenAICodexResponses = (model, context, options) => {
|
|
|
16838
17007
|
throw new Error(`No API key for provider: ${model.provider}`);
|
|
16839
17008
|
}
|
|
16840
17009
|
const base = buildBaseOptions(model, options, apiKey);
|
|
16841
|
-
const
|
|
17010
|
+
const mappedEffort = options?.reasoning === "max" && model.reasoningEfforts?.includes("max") ? "max" : mapThinkingLevel(options?.reasoning, supportsXhigh(model) ? "supports-xhigh" : "clamp-xhigh");
|
|
17011
|
+
const reasoningEffort = mappedEffort && model.reasoningEfforts && (mappedEffort === "minimal" || !model.reasoningEfforts.includes(mappedEffort)) ? void 0 : mappedEffort;
|
|
16842
17012
|
return streamOpenAICodexResponses(model, context, {
|
|
16843
17013
|
...base,
|
|
16844
17014
|
reasoningEffort
|
|
@@ -16860,7 +17030,11 @@ function buildRequestBody(model, context, options) {
|
|
|
16860
17030
|
tool_choice: "auto",
|
|
16861
17031
|
parallel_tool_calls: true
|
|
16862
17032
|
};
|
|
16863
|
-
|
|
17033
|
+
const usesFixedGpt6CodexPayload = (/* @__PURE__ */ new Set(["gpt-6-astra", "gpt-6-sol", "gpt-6-luna"])).has(model.id);
|
|
17034
|
+
if (options?.maxTokens !== void 0 && !usesFixedGpt6CodexPayload) {
|
|
17035
|
+
body.max_output_tokens = options.maxTokens;
|
|
17036
|
+
}
|
|
17037
|
+
if (options?.temperature !== void 0 && !usesFixedGpt6CodexPayload) {
|
|
16864
17038
|
body.temperature = options.temperature;
|
|
16865
17039
|
}
|
|
16866
17040
|
if (context.tools) {
|
|
@@ -17517,7 +17691,8 @@ var CLAUDE_THINKING_BUDGETS = {
|
|
|
17517
17691
|
low: 1500,
|
|
17518
17692
|
medium: 6e3,
|
|
17519
17693
|
high: 2e4,
|
|
17520
|
-
xhigh: 2e4
|
|
17694
|
+
xhigh: 2e4,
|
|
17695
|
+
max: 2e4
|
|
17521
17696
|
};
|
|
17522
17697
|
function resolveThinkingPayload(model, options) {
|
|
17523
17698
|
if (!options.reasoning || !model.reasoning) {
|