perchai-cli 2.4.46 → 2.4.48
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/perch.mjs +770 -132
- package/package.json +1 -1
package/dist/perch.mjs
CHANGED
|
@@ -75566,6 +75566,7 @@ var init_payroll = __esm({
|
|
|
75566
75566
|
// lib/perchBusinessTools/index.ts
|
|
75567
75567
|
var init_perchBusinessTools = __esm({
|
|
75568
75568
|
"lib/perchBusinessTools/index.ts"() {
|
|
75569
|
+
"use strict";
|
|
75569
75570
|
init_generateAPAuditPacket();
|
|
75570
75571
|
init_inventoryFolder();
|
|
75571
75572
|
init_loadBusinessTables();
|
|
@@ -75917,6 +75918,7 @@ function isTurnAbortedError(error) {
|
|
|
75917
75918
|
var TURN_STOPPED_BY_USER_MESSAGE;
|
|
75918
75919
|
var init_turnAbort = __esm({
|
|
75919
75920
|
"features/perchTerminal/runtime/turnAbort.ts"() {
|
|
75921
|
+
"use strict";
|
|
75920
75922
|
TURN_STOPPED_BY_USER_MESSAGE = "Turn stopped by user.";
|
|
75921
75923
|
}
|
|
75922
75924
|
});
|
|
@@ -76222,6 +76224,7 @@ function getToolDisplayName(toolName) {
|
|
|
76222
76224
|
var NON_MODULE_TOOL_OWNERS, TOOL_RISK, TOOL_DISPLAY_NAMES;
|
|
76223
76225
|
var init_catalog = __esm({
|
|
76224
76226
|
"features/perchTerminal/runtime/toolSystem/catalog.ts"() {
|
|
76227
|
+
"use strict";
|
|
76225
76228
|
init_toolNames();
|
|
76226
76229
|
NON_MODULE_TOOL_OWNERS = {
|
|
76227
76230
|
[TOOL_NAMES.listSources]: "lane",
|
|
@@ -84008,7 +84011,7 @@ function sanitizeModelBackendPreset(value) {
|
|
|
84008
84011
|
if (value === "wandb_gemma") return "wandb_qwen";
|
|
84009
84012
|
if (value === "wandb_glm") return "wandb_glm51";
|
|
84010
84013
|
if (value === "bedrock_mistral_large_3") return "bedrock_qwen3_coder";
|
|
84011
|
-
if (value === "router" || value === "gcp" || value === "modal" || value === "huggingface" || value === "fireworks_deepseek" || value === "wandb_qwen" || value === "wandb_minimax" || value === "wandb_kimi" || value === "wandb_glm51" || value === "wandb_nemotron_ultra" || value === "bedrock_glm5" || value === "bedrock_qwen3_coder" || value === "bedrock_gpt_oss_120b" || value === "bedrock_nemotron_super" || value === "bedrock_minimax_m2" || value === "bedrock_deepseek_v32" || value === "bedrock_qwen3_vl" || value === "codex_gpt55" || value === "codex_gpt54" || value === "codex_gpt54_mini" || value === "claude_haiku45" || value === "claude_sonnet46" || value === "claude_opus48") {
|
|
84014
|
+
if (value === "router" || value === "gcp" || value === "modal" || value === "huggingface" || value === "fireworks_deepseek" || value === "wandb_qwen" || value === "wandb_minimax" || value === "wandb_kimi" || value === "wandb_glm51" || value === "wandb_nemotron_ultra" || value === "wandb_deepseek_flash" || value === "wandb_deepseek_pro" || value === "bedrock_kimi_k25" || value === "bedrock_glm5" || value === "bedrock_qwen3_coder" || value === "bedrock_gpt_oss_120b" || value === "bedrock_nemotron_super" || value === "bedrock_minimax_m2" || value === "bedrock_deepseek_v32" || value === "bedrock_qwen3_vl" || value === "codex_gpt55" || value === "codex_gpt54" || value === "codex_gpt54_mini" || value === "claude_haiku45" || value === "claude_sonnet46" || value === "claude_opus48") {
|
|
84012
84015
|
return value;
|
|
84013
84016
|
}
|
|
84014
84017
|
return null;
|
|
@@ -84120,7 +84123,7 @@ function resolveApiModelId(option, env4 = runtimeEnv()) {
|
|
|
84120
84123
|
}
|
|
84121
84124
|
return option.modelId;
|
|
84122
84125
|
}
|
|
84123
|
-
var DEFAULT_NIM_MODEL_ID, DEFAULT_FOUNDER_MODEL_OPTION_ID, ALL_MODEL_LANES, WORKER_LANES, REASONING_LANES, DEFAULT_GITHUB_GPT_41_ID, DEFAULT_GITHUB_GPT_41_MINI_ID, DEFAULT_GITHUB_GPT_4O_ID, DEFAULT_CODE_WORKER_MODEL_ID, GCP_SELF_HOSTED_OPTION_ID, DEFAULT_GCP_INFERENCE_MODEL, MODAL_SELF_HOSTED_OPTION_ID, MODAL_MIMO_OPTION_ID, DEFAULT_MODAL_INFERENCE_MODEL, HUGGINGFACE_KIMI_K25_OPTION_ID, WANDB_QWEN_36_35B_A3B_OPTION_ID, WANDB_MINIMAX_M25_OPTION_ID, WANDB_KIMI_K26_OPTION_ID, WANDB_GLM_51_OPTION_ID, WANDB_NEMOTRON_ULTRA_OPTION_ID, BEDROCK_GLM5_OPTION_ID, BEDROCK_QWEN3_CODER_480B_OPTION_ID, BEDROCK_GPT_OSS_120B_OPTION_ID, BEDROCK_NEMOTRON_SUPER_120B_OPTION_ID, BEDROCK_MINIMAX_M2_OPTION_ID, BEDROCK_DEEPSEEK_V32_OPTION_ID, BEDROCK_QWEN3_VL_235B_OPTION_ID, CODEX_GPT_55_OPTION_ID, CODEX_GPT_54_OPTION_ID, CODEX_GPT_54_MINI_OPTION_ID, CLAUDE_CODE_HAIKU_45_OPTION_ID, CLAUDE_CODE_SONNET_46_OPTION_ID, CLAUDE_CODE_OPUS_48_OPTION_ID, FIREWORKS_DEEPSEEK_V4_FLASH_OPTION_ID, FIREWORKS_DEEPSEEK_VISION_PRIMARY_OPTION_ID, FIREWORKS_DEEPSEEK_VISION_FALLBACK_OPTION_IDS, AUTO_ROUTER_EXCLUDED_BACKEND_OPTION_IDS, AI_GATEWAY_AUTO_ROUTER_OPTION_IDS, MODAL_MODELS, GCP_MODELS, HUGGINGFACE_MODELS, WANDB_MODELS, BEDROCK_MANTLE_MODELS, CODEX_OAUTH_MODELS, CLAUDE_CODE_OAUTH_MODELS, AI_GATEWAY_MODELS, OPENROUTER_MODELS, DEFAULT_OPERATOR_VISION_MODEL_ID, GITHUB_MODELS_VALIDATED_WORKERS, OPENAI_VALIDATED_WORKERS, RAW_FOUNDER_MODEL_OPTIONS, FOUNDER_MODEL_OPTIONS, DEFAULT_FOUNDER_MODEL_SELECTION;
|
|
84126
|
+
var DEFAULT_NIM_MODEL_ID, DEFAULT_FOUNDER_MODEL_OPTION_ID, ALL_MODEL_LANES, WORKER_LANES, REASONING_LANES, DEFAULT_GITHUB_GPT_41_ID, DEFAULT_GITHUB_GPT_41_MINI_ID, DEFAULT_GITHUB_GPT_4O_ID, DEFAULT_CODE_WORKER_MODEL_ID, GCP_SELF_HOSTED_OPTION_ID, DEFAULT_GCP_INFERENCE_MODEL, MODAL_SELF_HOSTED_OPTION_ID, MODAL_MIMO_OPTION_ID, DEFAULT_MODAL_INFERENCE_MODEL, HUGGINGFACE_KIMI_K25_OPTION_ID, WANDB_QWEN_36_35B_A3B_OPTION_ID, WANDB_MINIMAX_M25_OPTION_ID, WANDB_KIMI_K26_OPTION_ID, WANDB_GLM_51_OPTION_ID, WANDB_NEMOTRON_ULTRA_OPTION_ID, WANDB_DEEPSEEK_V4_FLASH_OPTION_ID, WANDB_DEEPSEEK_V4_PRO_OPTION_ID, BEDROCK_KIMI_K25_OPTION_ID, BEDROCK_GLM5_OPTION_ID, BEDROCK_QWEN3_CODER_480B_OPTION_ID, BEDROCK_GPT_OSS_120B_OPTION_ID, BEDROCK_NEMOTRON_SUPER_120B_OPTION_ID, BEDROCK_MINIMAX_M2_OPTION_ID, BEDROCK_DEEPSEEK_V32_OPTION_ID, BEDROCK_QWEN3_VL_235B_OPTION_ID, CODEX_GPT_55_OPTION_ID, CODEX_GPT_54_OPTION_ID, CODEX_GPT_54_MINI_OPTION_ID, CLAUDE_CODE_HAIKU_45_OPTION_ID, CLAUDE_CODE_SONNET_46_OPTION_ID, CLAUDE_CODE_OPUS_48_OPTION_ID, FIREWORKS_DEEPSEEK_V4_FLASH_OPTION_ID, FIREWORKS_DEEPSEEK_VISION_PRIMARY_OPTION_ID, FIREWORKS_DEEPSEEK_VISION_FALLBACK_OPTION_IDS, AUTO_ROUTER_EXCLUDED_BACKEND_OPTION_IDS, AI_GATEWAY_AUTO_ROUTER_OPTION_IDS, MODAL_MODELS, GCP_MODELS, HUGGINGFACE_MODELS, WANDB_MODELS, BEDROCK_MANTLE_MODELS, CODEX_OAUTH_MODELS, CLAUDE_CODE_OAUTH_MODELS, AI_GATEWAY_MODELS, OPENROUTER_MODELS, DEFAULT_OPERATOR_VISION_MODEL_ID, GITHUB_MODELS_VALIDATED_WORKERS, OPENAI_VALIDATED_WORKERS, RAW_FOUNDER_MODEL_OPTIONS, FOUNDER_MODEL_OPTIONS, DEFAULT_FOUNDER_MODEL_SELECTION;
|
|
84124
84127
|
var init_modelRegistry = __esm({
|
|
84125
84128
|
"features/perchTerminal/runtime/modelRegistry.ts"() {
|
|
84126
84129
|
"use strict";
|
|
@@ -84166,6 +84169,18 @@ var init_modelRegistry = __esm({
|
|
|
84166
84169
|
WANDB_KIMI_K26_OPTION_ID = "wandb-kimi-k2-6";
|
|
84167
84170
|
WANDB_GLM_51_OPTION_ID = "wandb-zai-org-glm-5-1";
|
|
84168
84171
|
WANDB_NEMOTRON_ULTRA_OPTION_ID = "wandb-nvidia-nvidia-nemotron-3-ultra-550b-a55b";
|
|
84172
|
+
WANDB_DEEPSEEK_V4_FLASH_OPTION_ID = makeModelOptionId(
|
|
84173
|
+
"wandb",
|
|
84174
|
+
"deepseek-ai/DeepSeek-V4-Flash"
|
|
84175
|
+
);
|
|
84176
|
+
WANDB_DEEPSEEK_V4_PRO_OPTION_ID = makeModelOptionId(
|
|
84177
|
+
"wandb",
|
|
84178
|
+
"deepseek-ai/DeepSeek-V4-Pro"
|
|
84179
|
+
);
|
|
84180
|
+
BEDROCK_KIMI_K25_OPTION_ID = makeModelOptionId(
|
|
84181
|
+
"bedrock_mantle",
|
|
84182
|
+
"moonshotai.kimi-k2.5"
|
|
84183
|
+
);
|
|
84169
84184
|
BEDROCK_GLM5_OPTION_ID = makeModelOptionId("bedrock_mantle", "zai.glm-5");
|
|
84170
84185
|
BEDROCK_QWEN3_CODER_480B_OPTION_ID = makeModelOptionId(
|
|
84171
84186
|
"bedrock_mantle",
|
|
@@ -84230,6 +84245,9 @@ var init_modelRegistry = __esm({
|
|
|
84230
84245
|
WANDB_KIMI_K26_OPTION_ID,
|
|
84231
84246
|
WANDB_GLM_51_OPTION_ID,
|
|
84232
84247
|
WANDB_NEMOTRON_ULTRA_OPTION_ID,
|
|
84248
|
+
WANDB_DEEPSEEK_V4_FLASH_OPTION_ID,
|
|
84249
|
+
WANDB_DEEPSEEK_V4_PRO_OPTION_ID,
|
|
84250
|
+
BEDROCK_KIMI_K25_OPTION_ID,
|
|
84233
84251
|
BEDROCK_GLM5_OPTION_ID,
|
|
84234
84252
|
BEDROCK_QWEN3_CODER_480B_OPTION_ID,
|
|
84235
84253
|
BEDROCK_GPT_OSS_120B_OPTION_ID,
|
|
@@ -84456,9 +84474,79 @@ var init_modelRegistry = __esm({
|
|
|
84456
84474
|
availabilityNote: "W&B Inference hosted Nemotron 3 Ultra. Text/tools use W&B; browser/image tasks use the NIM vision observer chain when selected."
|
|
84457
84475
|
}),
|
|
84458
84476
|
id: WANDB_NEMOTRON_ULTRA_OPTION_ID
|
|
84477
|
+
},
|
|
84478
|
+
{
|
|
84479
|
+
...makeManualModelOption({
|
|
84480
|
+
providerId: "wandb",
|
|
84481
|
+
modelId: "deepseek-ai/DeepSeek-V4-Flash",
|
|
84482
|
+
label: "W&B \xB7 DeepSeek V4 Flash",
|
|
84483
|
+
providerLabel: "Weights & Biases",
|
|
84484
|
+
vendor: "DeepSeek",
|
|
84485
|
+
family: "V4 Flash",
|
|
84486
|
+
groupLabel: "Hosted / W&B Inference",
|
|
84487
|
+
contextWindow: 104e4,
|
|
84488
|
+
lanes: ALL_MODEL_LANES,
|
|
84489
|
+
reasoningSupport: "false",
|
|
84490
|
+
envKey: "WANDB_API_KEY",
|
|
84491
|
+
adapterStatus: "wired",
|
|
84492
|
+
modality: "chat",
|
|
84493
|
+
capabilities: ["code", "agentic_coding"],
|
|
84494
|
+
costTier: "standard",
|
|
84495
|
+
userFacing: true,
|
|
84496
|
+
manualOnly: true,
|
|
84497
|
+
availabilityNote: "W&B Inference hosted DeepSeek V4 Flash. Text/tools use WANDB_API_KEY; browser/image tasks use the NIM vision observer chain when the W&B DeepSeek Flash backend card is selected."
|
|
84498
|
+
}),
|
|
84499
|
+
id: WANDB_DEEPSEEK_V4_FLASH_OPTION_ID
|
|
84500
|
+
},
|
|
84501
|
+
{
|
|
84502
|
+
...makeManualModelOption({
|
|
84503
|
+
providerId: "wandb",
|
|
84504
|
+
modelId: "deepseek-ai/DeepSeek-V4-Pro",
|
|
84505
|
+
label: "W&B \xB7 DeepSeek V4 Pro",
|
|
84506
|
+
providerLabel: "Weights & Biases",
|
|
84507
|
+
vendor: "DeepSeek",
|
|
84508
|
+
family: "V4 Pro",
|
|
84509
|
+
groupLabel: "Hosted / W&B Inference",
|
|
84510
|
+
contextWindow: 104e4,
|
|
84511
|
+
lanes: ALL_MODEL_LANES,
|
|
84512
|
+
reasoningSupport: "false",
|
|
84513
|
+
envKey: "WANDB_API_KEY",
|
|
84514
|
+
adapterStatus: "wired",
|
|
84515
|
+
modality: "chat",
|
|
84516
|
+
capabilities: ["code", "agentic_coding"],
|
|
84517
|
+
costTier: "premium",
|
|
84518
|
+
userFacing: true,
|
|
84519
|
+
manualOnly: true,
|
|
84520
|
+
availabilityNote: "W&B Inference hosted DeepSeek V4 Pro. Text/tools use WANDB_API_KEY; browser/image tasks use the NIM vision observer chain when the W&B DeepSeek Pro backend card is selected."
|
|
84521
|
+
}),
|
|
84522
|
+
id: WANDB_DEEPSEEK_V4_PRO_OPTION_ID
|
|
84459
84523
|
}
|
|
84460
84524
|
];
|
|
84461
84525
|
BEDROCK_MANTLE_MODELS = [
|
|
84526
|
+
{
|
|
84527
|
+
...makeManualModelOption({
|
|
84528
|
+
providerId: "bedrock_mantle",
|
|
84529
|
+
modelId: "moonshotai.kimi-k2.5",
|
|
84530
|
+
label: "Bedrock Mantle \xB7 Kimi K2.5 Vision",
|
|
84531
|
+
providerLabel: "Bedrock Mantle",
|
|
84532
|
+
vendor: "Moonshot AI",
|
|
84533
|
+
family: "Kimi K2.5",
|
|
84534
|
+
groupLabel: "Hosted / Bedrock Mantle",
|
|
84535
|
+
contextWindow: 256e3,
|
|
84536
|
+
maxOutputTokens: 16e3,
|
|
84537
|
+
lanes: [...ALL_MODEL_LANES, "vision"],
|
|
84538
|
+
reasoningSupport: "false",
|
|
84539
|
+
envKey: "BEDROCK_MANTLE_API_KEY",
|
|
84540
|
+
adapterStatus: "wired",
|
|
84541
|
+
modality: "vision",
|
|
84542
|
+
capabilities: ["vision", "multimodal", "code", "agentic_coding"],
|
|
84543
|
+
costTier: "premium",
|
|
84544
|
+
userFacing: true,
|
|
84545
|
+
manualOnly: true,
|
|
84546
|
+
availabilityNote: "Bedrock Mantle Kimi K2.5 multimodal. Native vision on moonshotai.kimi-k2.5; uses BEDROCK_MANTLE_API_KEY and BEDROCK_MANTLE_BASE_URL if set."
|
|
84547
|
+
}),
|
|
84548
|
+
id: BEDROCK_KIMI_K25_OPTION_ID
|
|
84549
|
+
},
|
|
84462
84550
|
{
|
|
84463
84551
|
...makeManualModelOption({
|
|
84464
84552
|
providerId: "bedrock_mantle",
|
|
@@ -86736,7 +86824,6 @@ function truncateHistoryLine(value, max2) {
|
|
|
86736
86824
|
}
|
|
86737
86825
|
var init_operatorTruth = __esm({
|
|
86738
86826
|
"features/perchTerminal/runtime/operatorTruth.ts"() {
|
|
86739
|
-
"use strict";
|
|
86740
86827
|
}
|
|
86741
86828
|
});
|
|
86742
86829
|
|
|
@@ -116243,6 +116330,33 @@ var init_inferenceCost = __esm({
|
|
|
116243
116330
|
outputUsdPer1k: 275e-5,
|
|
116244
116331
|
cachedInputUsdPer1k: 15e-5
|
|
116245
116332
|
},
|
|
116333
|
+
[WANDB_DEEPSEEK_V4_FLASH_OPTION_ID]: {
|
|
116334
|
+
modelOptionId: WANDB_DEEPSEEK_V4_FLASH_OPTION_ID,
|
|
116335
|
+
providerId: "wandb",
|
|
116336
|
+
modelId: "deepseek-ai/DeepSeek-V4-Flash",
|
|
116337
|
+
label: "W&B DeepSeek V4 Flash",
|
|
116338
|
+
inputUsdPer1k: 14e-5,
|
|
116339
|
+
outputUsdPer1k: 28e-5,
|
|
116340
|
+
cachedInputUsdPer1k: 7e-5
|
|
116341
|
+
},
|
|
116342
|
+
[WANDB_DEEPSEEK_V4_PRO_OPTION_ID]: {
|
|
116343
|
+
modelOptionId: WANDB_DEEPSEEK_V4_PRO_OPTION_ID,
|
|
116344
|
+
providerId: "wandb",
|
|
116345
|
+
modelId: "deepseek-ai/DeepSeek-V4-Pro",
|
|
116346
|
+
label: "W&B DeepSeek V4 Pro",
|
|
116347
|
+
inputUsdPer1k: 174e-5,
|
|
116348
|
+
outputUsdPer1k: 348e-5,
|
|
116349
|
+
cachedInputUsdPer1k: 14e-5
|
|
116350
|
+
},
|
|
116351
|
+
[BEDROCK_KIMI_K25_OPTION_ID]: {
|
|
116352
|
+
modelOptionId: BEDROCK_KIMI_K25_OPTION_ID,
|
|
116353
|
+
providerId: "bedrock_mantle",
|
|
116354
|
+
modelId: "moonshotai.kimi-k2.5",
|
|
116355
|
+
label: "Bedrock Mantle \xB7 Kimi K2.5 Vision",
|
|
116356
|
+
inputUsdPer1k: 6e-4,
|
|
116357
|
+
outputUsdPer1k: 3e-3,
|
|
116358
|
+
cachedInputUsdPer1k: 6e-4
|
|
116359
|
+
},
|
|
116246
116360
|
[BEDROCK_GLM5_OPTION_ID]: {
|
|
116247
116361
|
modelOptionId: BEDROCK_GLM5_OPTION_ID,
|
|
116248
116362
|
providerId: "bedrock_mantle",
|
|
@@ -118544,8 +118658,15 @@ function buildBody(option, opts, model, stream, includeResponseFormat = true) {
|
|
|
118544
118658
|
body.tool_choice = opts.toolChoice ?? "auto";
|
|
118545
118659
|
}
|
|
118546
118660
|
if (includeResponseFormat && opts.responseFormat) body.response_format = opts.responseFormat;
|
|
118547
|
-
|
|
118548
|
-
|
|
118661
|
+
const reasoning = opts.reasoning;
|
|
118662
|
+
if (option.providerId === "wandb") {
|
|
118663
|
+
if (reasoning && typeof reasoning.enableThinking === "boolean") {
|
|
118664
|
+
body.chat_template_kwargs = { enable_thinking: reasoning.enableThinking };
|
|
118665
|
+
} else if (option.modelId.startsWith("Qwen/")) {
|
|
118666
|
+
body.chat_template_kwargs = { enable_thinking: false };
|
|
118667
|
+
}
|
|
118668
|
+
} else if (reasoning?.reasoningEffort && (option.providerId === "bedrock_mantle" || option.providerId === "cerebras")) {
|
|
118669
|
+
body.reasoning_effort = reasoning.reasoningEffort;
|
|
118549
118670
|
}
|
|
118550
118671
|
if (stream) {
|
|
118551
118672
|
body.stream = true;
|
|
@@ -118992,7 +119113,98 @@ var init_autoRouter = __esm({
|
|
|
118992
119113
|
}
|
|
118993
119114
|
});
|
|
118994
119115
|
|
|
119116
|
+
// lib/auth/browserSession.ts
|
|
119117
|
+
async function syncBrowserAuthSession() {
|
|
119118
|
+
if (typeof window === "undefined") return null;
|
|
119119
|
+
const response = await fetch("/api/auth/session", SESSION_FETCH_OPTIONS);
|
|
119120
|
+
if (!response.ok) return null;
|
|
119121
|
+
const body = await response.json();
|
|
119122
|
+
return body.session ?? null;
|
|
119123
|
+
}
|
|
119124
|
+
var SESSION_FETCH_OPTIONS;
|
|
119125
|
+
var init_browserSession = __esm({
|
|
119126
|
+
"lib/auth/browserSession.ts"() {
|
|
119127
|
+
SESSION_FETCH_OPTIONS = {
|
|
119128
|
+
credentials: "same-origin",
|
|
119129
|
+
cache: "no-store"
|
|
119130
|
+
};
|
|
119131
|
+
}
|
|
119132
|
+
});
|
|
119133
|
+
|
|
119134
|
+
// features/perchTerminal/runtime/roost.ts
|
|
119135
|
+
function normalizeRoostTier(value) {
|
|
119136
|
+
if (value === "max") return "pro_max";
|
|
119137
|
+
return isRoostTier(value) ? value : null;
|
|
119138
|
+
}
|
|
119139
|
+
function normalizeRoostModelChoice(value) {
|
|
119140
|
+
if (value === "internal") return "internal";
|
|
119141
|
+
return normalizeRoostTier(value);
|
|
119142
|
+
}
|
|
119143
|
+
function isRoostTier(value) {
|
|
119144
|
+
return value === "standard" || value === "standard_max" || value === "pro" || value === "pro_max";
|
|
119145
|
+
}
|
|
119146
|
+
var ROOST_TIER_LABELS;
|
|
119147
|
+
var init_roost = __esm({
|
|
119148
|
+
"features/perchTerminal/runtime/roost.ts"() {
|
|
119149
|
+
"use strict";
|
|
119150
|
+
init_modelRegistry();
|
|
119151
|
+
ROOST_TIER_LABELS = {
|
|
119152
|
+
standard: "Standard",
|
|
119153
|
+
standard_max: "Standard Max",
|
|
119154
|
+
pro: "Pro",
|
|
119155
|
+
pro_max: "Pro Max"
|
|
119156
|
+
};
|
|
119157
|
+
}
|
|
119158
|
+
});
|
|
119159
|
+
|
|
119160
|
+
// features/perchTerminal/runtime/roostUserSelectionClient.ts
|
|
119161
|
+
function coerceSelection(raw) {
|
|
119162
|
+
const choice = normalizeRoostModelChoice(raw?.choice);
|
|
119163
|
+
return {
|
|
119164
|
+
choice: choice ?? DEFAULT_ROOST_USER_SELECTION.choice,
|
|
119165
|
+
reasoningEnabled: typeof raw?.reasoningEnabled === "boolean" ? raw.reasoningEnabled : DEFAULT_ROOST_USER_SELECTION.reasoningEnabled
|
|
119166
|
+
};
|
|
119167
|
+
}
|
|
119168
|
+
function peekStoredRoostUserSelection() {
|
|
119169
|
+
if (typeof window === "undefined") return null;
|
|
119170
|
+
try {
|
|
119171
|
+
const raw = window.localStorage.getItem(ROOST_USER_SELECTION_STORAGE_KEY);
|
|
119172
|
+
if (!raw) return null;
|
|
119173
|
+
return coerceSelection(JSON.parse(raw));
|
|
119174
|
+
} catch {
|
|
119175
|
+
return null;
|
|
119176
|
+
}
|
|
119177
|
+
}
|
|
119178
|
+
function setRoostUserSelectionForNode(selection) {
|
|
119179
|
+
nodeSelectionOverride = selection ? coerceSelection(selection) : null;
|
|
119180
|
+
}
|
|
119181
|
+
function getEffectiveRoostUserSelection() {
|
|
119182
|
+
if (typeof window !== "undefined") return peekStoredRoostUserSelection();
|
|
119183
|
+
return nodeSelectionOverride;
|
|
119184
|
+
}
|
|
119185
|
+
var ROOST_USER_SELECTION_STORAGE_KEY, DEFAULT_ROOST_USER_SELECTION, nodeSelectionOverride;
|
|
119186
|
+
var init_roostUserSelectionClient = __esm({
|
|
119187
|
+
"features/perchTerminal/runtime/roostUserSelectionClient.ts"() {
|
|
119188
|
+
"use strict";
|
|
119189
|
+
init_roost();
|
|
119190
|
+
ROOST_USER_SELECTION_STORAGE_KEY = "perch.roostUserSelection.v1";
|
|
119191
|
+
DEFAULT_ROOST_USER_SELECTION = {
|
|
119192
|
+
choice: "standard",
|
|
119193
|
+
reasoningEnabled: true
|
|
119194
|
+
};
|
|
119195
|
+
nodeSelectionOverride = null;
|
|
119196
|
+
}
|
|
119197
|
+
});
|
|
119198
|
+
|
|
118995
119199
|
// features/perchTerminal/runtime/modelRouter.ts
|
|
119200
|
+
function roostUserSelectionBodyFields() {
|
|
119201
|
+
const selection = getEffectiveRoostUserSelection();
|
|
119202
|
+
if (!selection) return {};
|
|
119203
|
+
return {
|
|
119204
|
+
roostModelChoice: selection.choice,
|
|
119205
|
+
roostReasoning: selection.reasoningEnabled
|
|
119206
|
+
};
|
|
119207
|
+
}
|
|
118996
119208
|
async function callModelRouter(_config, request, opts) {
|
|
118997
119209
|
const explicitProxyUrl = resolveModelCallProxyUrl(opts?.cliServerAppUrl ?? null);
|
|
118998
119210
|
if (typeof window !== "undefined") {
|
|
@@ -119019,7 +119231,8 @@ async function callModelRouter(_config, request, opts) {
|
|
|
119019
119231
|
responseFormat: request.responseFormat,
|
|
119020
119232
|
preferredModelId: opts?.preferredModelId ?? null,
|
|
119021
119233
|
avoidModelIds: opts?.avoidModelIds,
|
|
119022
|
-
attribution: opts?.attribution ?? null
|
|
119234
|
+
attribution: opts?.attribution ?? null,
|
|
119235
|
+
reasoning: opts?.reasoning ?? null
|
|
119023
119236
|
};
|
|
119024
119237
|
try {
|
|
119025
119238
|
if (request.onChunk || request.onReasoningChunk || request.onStreamEvent) {
|
|
@@ -119145,7 +119358,8 @@ async function callModelRouterViaServer(request, opts, endpoint = "/api/perch-te
|
|
|
119145
119358
|
raceMode: opts?.raceMode,
|
|
119146
119359
|
preferredModelId: opts?.preferredModelId ?? null,
|
|
119147
119360
|
avoidModelIds: opts?.avoidModelIds ?? [],
|
|
119148
|
-
attribution: opts?.attribution ?? null
|
|
119361
|
+
attribution: opts?.attribution ?? null,
|
|
119362
|
+
...roostUserSelectionBodyFields()
|
|
119149
119363
|
});
|
|
119150
119364
|
const response = await fetchModelProxyWithRetry(endpoint, {
|
|
119151
119365
|
method: "POST",
|
|
@@ -119277,9 +119491,18 @@ async function callModelRouterViaServer(request, opts, endpoint = "/api/perch-te
|
|
|
119277
119491
|
async function fetchModelProxyWithRetry(endpoint, init, options) {
|
|
119278
119492
|
const maxAttempts = Math.max(1, options?.maxAttempts ?? MODEL_PROXY_MAX_ATTEMPTS);
|
|
119279
119493
|
let lastError = null;
|
|
119494
|
+
let authSynced = false;
|
|
119280
119495
|
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
119281
119496
|
try {
|
|
119282
119497
|
const response = await fetch(endpoint, init);
|
|
119498
|
+
if (response.status === 401 && !authSynced && typeof globalThis.window !== "undefined") {
|
|
119499
|
+
authSynced = true;
|
|
119500
|
+
await syncBrowserAuthSession();
|
|
119501
|
+
options?.onRetry?.(attempt, "HTTP 401 (session sync)");
|
|
119502
|
+
await response.body?.cancel().catch(() => void 0);
|
|
119503
|
+
await waitForModelProxyRetry(attempt, init.signal);
|
|
119504
|
+
continue;
|
|
119505
|
+
}
|
|
119283
119506
|
if (!isRetriableModelProxyStatus(response.status) || attempt === maxAttempts - 1) {
|
|
119284
119507
|
return response;
|
|
119285
119508
|
}
|
|
@@ -119413,6 +119636,8 @@ var init_modelRouter = __esm({
|
|
|
119413
119636
|
init_modelRegistry();
|
|
119414
119637
|
init_contextMeter();
|
|
119415
119638
|
init_inferenceUsageRecorder();
|
|
119639
|
+
init_browserSession();
|
|
119640
|
+
init_roostUserSelectionClient();
|
|
119416
119641
|
init_providerModelStep();
|
|
119417
119642
|
init_toolCallNormalizer();
|
|
119418
119643
|
MODEL_CALL_PROXY_ENV = "PERCH_MODEL_CALL_PROXY_URL";
|
|
@@ -119432,7 +119657,7 @@ var init_accountHelpers = __esm({
|
|
|
119432
119657
|
|
|
119433
119658
|
// features/perchTerminal/runtime/fireworksDeepSeekPreset.ts
|
|
119434
119659
|
function usesNimVisionObserverPreset(selection) {
|
|
119435
|
-
return selection?.modelBackendPreset === "fireworks_deepseek" || selection?.modelBackendPreset === "wandb_minimax" || selection?.modelBackendPreset === "wandb_glm51" || selection?.modelBackendPreset === "wandb_nemotron_ultra" || selection?.modelBackendPreset === "bedrock_glm5" || selection?.modelBackendPreset === "bedrock_qwen3_coder" || selection?.modelBackendPreset === "bedrock_gpt_oss_120b" || selection?.modelBackendPreset === "bedrock_nemotron_super" || selection?.modelBackendPreset === "bedrock_minimax_m2" || selection?.modelBackendPreset === "bedrock_deepseek_v32";
|
|
119660
|
+
return selection?.modelBackendPreset === "fireworks_deepseek" || selection?.modelBackendPreset === "wandb_minimax" || selection?.modelBackendPreset === "wandb_glm51" || selection?.modelBackendPreset === "wandb_nemotron_ultra" || selection?.modelBackendPreset === "wandb_deepseek_flash" || selection?.modelBackendPreset === "wandb_deepseek_pro" || selection?.modelBackendPreset === "bedrock_glm5" || selection?.modelBackendPreset === "bedrock_qwen3_coder" || selection?.modelBackendPreset === "bedrock_gpt_oss_120b" || selection?.modelBackendPreset === "bedrock_nemotron_super" || selection?.modelBackendPreset === "bedrock_minimax_m2" || selection?.modelBackendPreset === "bedrock_deepseek_v32";
|
|
119436
119661
|
}
|
|
119437
119662
|
function resolveVisionOptionChain(selection) {
|
|
119438
119663
|
const chain2 = [];
|
|
@@ -138907,6 +139132,7 @@ function offSandboxEvent(runId, handler) {
|
|
|
138907
139132
|
var LOCAL_WORKSPACE_ACCESS_UNAVAILABLE;
|
|
138908
139133
|
var init_bridge = __esm({
|
|
138909
139134
|
"features/perchTerminal/desktop/bridge.ts"() {
|
|
139135
|
+
"use strict";
|
|
138910
139136
|
LOCAL_WORKSPACE_ACCESS_UNAVAILABLE = "Local workspace access is unavailable. Open Perch Desktop or update the app.";
|
|
138911
139137
|
}
|
|
138912
139138
|
});
|
|
@@ -223449,6 +223675,12 @@ var init_usageCommand = __esm({
|
|
|
223449
223675
|
}
|
|
223450
223676
|
});
|
|
223451
223677
|
|
|
223678
|
+
// lib/perch-ai/entitlements.ts
|
|
223679
|
+
var init_entitlements = __esm({
|
|
223680
|
+
"lib/perch-ai/entitlements.ts"() {
|
|
223681
|
+
}
|
|
223682
|
+
});
|
|
223683
|
+
|
|
223452
223684
|
// lib/perch-ai/access.ts
|
|
223453
223685
|
function hasPrivilegedPerchAiRole(memberships) {
|
|
223454
223686
|
return memberships.some(
|
|
@@ -223466,6 +223698,296 @@ function canShowPerchDevTools(membershipRole) {
|
|
|
223466
223698
|
}
|
|
223467
223699
|
var init_access = __esm({
|
|
223468
223700
|
"lib/perch-ai/access.ts"() {
|
|
223701
|
+
init_entitlements();
|
|
223702
|
+
}
|
|
223703
|
+
});
|
|
223704
|
+
|
|
223705
|
+
// lib/perch-ai/perchTokens.ts
|
|
223706
|
+
function usdToPerchTokens(usd) {
|
|
223707
|
+
if (typeof usd !== "number" || !Number.isFinite(usd) || usd <= 0) return 0;
|
|
223708
|
+
return Math.ceil(usd / PERCH_TOKEN_USD);
|
|
223709
|
+
}
|
|
223710
|
+
function nullableUsdToPerchTokens(usd) {
|
|
223711
|
+
const tokens = usdToPerchTokens(usd);
|
|
223712
|
+
return tokens > 0 ? tokens : null;
|
|
223713
|
+
}
|
|
223714
|
+
function usdLimitToPerchTokens(usd) {
|
|
223715
|
+
if (!Number.isFinite(usd) || usd <= 0) return 0;
|
|
223716
|
+
return Math.round(usd / PERCH_TOKEN_USD);
|
|
223717
|
+
}
|
|
223718
|
+
var PERCH_TOKEN_USD, DEFAULT_PILOT_DAILY_LIMIT_USD, DEFAULT_PILOT_MONTHLY_LIMIT_USD;
|
|
223719
|
+
var init_perchTokens = __esm({
|
|
223720
|
+
"lib/perch-ai/perchTokens.ts"() {
|
|
223721
|
+
PERCH_TOKEN_USD = 1e-3;
|
|
223722
|
+
DEFAULT_PILOT_DAILY_LIMIT_USD = 5;
|
|
223723
|
+
DEFAULT_PILOT_MONTHLY_LIMIT_USD = DEFAULT_PILOT_DAILY_LIMIT_USD * 30;
|
|
223724
|
+
}
|
|
223725
|
+
});
|
|
223726
|
+
|
|
223727
|
+
// features/perchTerminal/persistence/usagePersistence.ts
|
|
223728
|
+
function startOfLocalDay() {
|
|
223729
|
+
const date = /* @__PURE__ */ new Date();
|
|
223730
|
+
date.setHours(0, 0, 0, 0);
|
|
223731
|
+
return date.toISOString();
|
|
223732
|
+
}
|
|
223733
|
+
function startOfRollingWeek() {
|
|
223734
|
+
const date = /* @__PURE__ */ new Date();
|
|
223735
|
+
date.setDate(date.getDate() - 7);
|
|
223736
|
+
return date.toISOString();
|
|
223737
|
+
}
|
|
223738
|
+
function startOfLocalMonth() {
|
|
223739
|
+
const date = /* @__PURE__ */ new Date();
|
|
223740
|
+
date.setDate(1);
|
|
223741
|
+
date.setHours(0, 0, 0, 0);
|
|
223742
|
+
return date.toISOString();
|
|
223743
|
+
}
|
|
223744
|
+
function sumPt(rows, since) {
|
|
223745
|
+
const total = rows.filter((row) => Date.parse(row.created_at) >= Date.parse(since)).reduce((sum, row) => sum + row.total_pt, 0);
|
|
223746
|
+
return total > 0 ? total : null;
|
|
223747
|
+
}
|
|
223748
|
+
function filterInferenceRows(rows, since) {
|
|
223749
|
+
return rows.filter((row) => Date.parse(row.created_at) >= Date.parse(since));
|
|
223750
|
+
}
|
|
223751
|
+
function sumInferenceCost(rows, since) {
|
|
223752
|
+
const total = filterInferenceRows(rows, since).reduce(
|
|
223753
|
+
(sum, row) => sum + Number(row.estimated_cost_usd ?? 0),
|
|
223754
|
+
0
|
|
223755
|
+
);
|
|
223756
|
+
return total > 0 ? total : null;
|
|
223757
|
+
}
|
|
223758
|
+
function sumInferenceTokens(rows, since) {
|
|
223759
|
+
const total = filterInferenceRows(rows, since).reduce(
|
|
223760
|
+
(sum, row) => sum + Number(row.total_tokens ?? 0),
|
|
223761
|
+
0
|
|
223762
|
+
);
|
|
223763
|
+
return total > 0 ? total : null;
|
|
223764
|
+
}
|
|
223765
|
+
function countInferenceCalls(rows, since) {
|
|
223766
|
+
const total = filterInferenceRows(rows, since).length;
|
|
223767
|
+
return total > 0 ? total : null;
|
|
223768
|
+
}
|
|
223769
|
+
function createUsagePersistence(supabase) {
|
|
223770
|
+
return {
|
|
223771
|
+
async listRateCards() {
|
|
223772
|
+
const { data, error } = await supabase.from("perch_ai_token_rate_cards").select("*").order("created_at", { ascending: false });
|
|
223773
|
+
if (error) throw error;
|
|
223774
|
+
return data ?? [];
|
|
223775
|
+
},
|
|
223776
|
+
async listUsageRawEvents({
|
|
223777
|
+
userId,
|
|
223778
|
+
workspaceId,
|
|
223779
|
+
limit = 50
|
|
223780
|
+
}) {
|
|
223781
|
+
const { data, error } = await supabase.from("perch_ai_usage_raw_events").select("*").eq("user_id", userId).eq("workspace_id", workspaceId).order("created_at", { ascending: false }).limit(limit);
|
|
223782
|
+
if (error) throw error;
|
|
223783
|
+
return data ?? [];
|
|
223784
|
+
},
|
|
223785
|
+
async listTokenCalculations({
|
|
223786
|
+
userId,
|
|
223787
|
+
workspaceId,
|
|
223788
|
+
since,
|
|
223789
|
+
limit = 250
|
|
223790
|
+
}) {
|
|
223791
|
+
let query = supabase.from("perch_ai_token_calculations").select("*").eq("user_id", userId).eq("workspace_id", workspaceId).order("created_at", { ascending: false }).limit(limit);
|
|
223792
|
+
if (since) query = query.gte("created_at", since);
|
|
223793
|
+
const { data, error } = await query;
|
|
223794
|
+
if (error) throw error;
|
|
223795
|
+
return data ?? [];
|
|
223796
|
+
},
|
|
223797
|
+
async listInferenceUsageRows({
|
|
223798
|
+
userId,
|
|
223799
|
+
workspaceId,
|
|
223800
|
+
since,
|
|
223801
|
+
limit = 250
|
|
223802
|
+
}) {
|
|
223803
|
+
let query = supabase.from("perch_ai_inference_usage").select("*").eq("user_id", userId).eq("workspace_id", workspaceId).order("created_at", { ascending: false }).limit(limit);
|
|
223804
|
+
if (since) query = query.gte("created_at", since);
|
|
223805
|
+
const { data, error } = await query;
|
|
223806
|
+
if (error) throw error;
|
|
223807
|
+
return data ?? [];
|
|
223808
|
+
},
|
|
223809
|
+
async getUsageMeter({
|
|
223810
|
+
userId,
|
|
223811
|
+
workspaceId
|
|
223812
|
+
}) {
|
|
223813
|
+
const localDay = startOfLocalDay();
|
|
223814
|
+
const rollingWeek = startOfRollingWeek();
|
|
223815
|
+
const localMonth = startOfLocalMonth();
|
|
223816
|
+
const [rows, inferenceRows] = await Promise.all([
|
|
223817
|
+
this.listTokenCalculations({
|
|
223818
|
+
userId,
|
|
223819
|
+
workspaceId,
|
|
223820
|
+
since: localMonth,
|
|
223821
|
+
limit: 5e3
|
|
223822
|
+
}),
|
|
223823
|
+
this.listInferenceUsageRows({
|
|
223824
|
+
userId,
|
|
223825
|
+
workspaceId,
|
|
223826
|
+
since: localMonth,
|
|
223827
|
+
limit: 5e3
|
|
223828
|
+
})
|
|
223829
|
+
]);
|
|
223830
|
+
const dailyUsd = sumInferenceCost(inferenceRows, localDay);
|
|
223831
|
+
const weeklyUsd = sumInferenceCost(inferenceRows, rollingWeek);
|
|
223832
|
+
const monthlyUsd = sumInferenceCost(inferenceRows, localMonth);
|
|
223833
|
+
return {
|
|
223834
|
+
dailyPt: nullableUsdToPerchTokens(dailyUsd) ?? sumPt(rows, localDay),
|
|
223835
|
+
weeklyPt: nullableUsdToPerchTokens(weeklyUsd) ?? sumPt(rows, rollingWeek),
|
|
223836
|
+
rows,
|
|
223837
|
+
dailyUsd,
|
|
223838
|
+
weeklyUsd,
|
|
223839
|
+
monthlyUsd,
|
|
223840
|
+
dailyTokens: sumInferenceTokens(inferenceRows, localDay),
|
|
223841
|
+
weeklyTokens: sumInferenceTokens(inferenceRows, rollingWeek),
|
|
223842
|
+
monthlyTokens: sumInferenceTokens(inferenceRows, localMonth),
|
|
223843
|
+
dailyCalls: countInferenceCalls(inferenceRows, localDay),
|
|
223844
|
+
weeklyCalls: countInferenceCalls(inferenceRows, rollingWeek),
|
|
223845
|
+
monthlyCalls: countInferenceCalls(inferenceRows, localMonth),
|
|
223846
|
+
inferenceRows
|
|
223847
|
+
};
|
|
223848
|
+
}
|
|
223849
|
+
};
|
|
223850
|
+
}
|
|
223851
|
+
var init_usagePersistence = __esm({
|
|
223852
|
+
"features/perchTerminal/persistence/usagePersistence.ts"() {
|
|
223853
|
+
init_perchTokens();
|
|
223854
|
+
}
|
|
223855
|
+
});
|
|
223856
|
+
|
|
223857
|
+
// features/perchTerminal/runtime/usage/usageAllowance.ts
|
|
223858
|
+
function readEntitlementNumber(value) {
|
|
223859
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
223860
|
+
if (typeof value === "string") {
|
|
223861
|
+
const parsed = Number(value);
|
|
223862
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
223863
|
+
}
|
|
223864
|
+
if (value && typeof value === "object") {
|
|
223865
|
+
const record = value;
|
|
223866
|
+
return readEntitlementNumber(record.usd) ?? readEntitlementNumber(record.amount) ?? readEntitlementNumber(record.value) ?? readEntitlementNumber(record.limit);
|
|
223867
|
+
}
|
|
223868
|
+
return null;
|
|
223869
|
+
}
|
|
223870
|
+
function readLimitUsd(entitlements, keys2, fallback) {
|
|
223871
|
+
for (const key of keys2) {
|
|
223872
|
+
const match = entitlements.find((entitlement) => entitlement.key === key);
|
|
223873
|
+
const value = match ? readEntitlementNumber(match.value_json) : null;
|
|
223874
|
+
if (value != null && value > 0) return value;
|
|
223875
|
+
}
|
|
223876
|
+
return fallback;
|
|
223877
|
+
}
|
|
223878
|
+
function isUnlimitedUsageSession(session) {
|
|
223879
|
+
if (!session) return false;
|
|
223880
|
+
return session.membershipRole === "admin" || session.membershipRole === "internal" || session.planCode === "internal";
|
|
223881
|
+
}
|
|
223882
|
+
function buildUsageAllowanceSnapshot(session, meter) {
|
|
223883
|
+
const unlimited = isUnlimitedUsageSession(session);
|
|
223884
|
+
const entitlements = session.entitlements ?? [];
|
|
223885
|
+
const dailyLimitUsd = readLimitUsd(
|
|
223886
|
+
entitlements,
|
|
223887
|
+
["usage_daily_usd", "daily_usage_usd", "pilot_daily_usd", "user_daily_cap_usd"],
|
|
223888
|
+
DEFAULT_PILOT_DAILY_LIMIT_USD
|
|
223889
|
+
);
|
|
223890
|
+
const monthlyLimitUsd = readLimitUsd(
|
|
223891
|
+
entitlements,
|
|
223892
|
+
["usage_monthly_usd", "monthly_usage_usd", "pilot_monthly_usd", "user_monthly_cap_usd"],
|
|
223893
|
+
DEFAULT_PILOT_MONTHLY_LIMIT_USD
|
|
223894
|
+
);
|
|
223895
|
+
return {
|
|
223896
|
+
unlimited,
|
|
223897
|
+
planLabel: session.planName ?? session.planCode ?? "Pilot",
|
|
223898
|
+
dailyUsedPt: meter?.dailyPt ?? usdToPerchTokens(meter?.dailyUsd),
|
|
223899
|
+
weeklyUsedPt: meter?.weeklyPt ?? usdToPerchTokens(meter?.weeklyUsd),
|
|
223900
|
+
monthlyUsedPt: usdToPerchTokens(meter?.monthlyUsd),
|
|
223901
|
+
dailyLimitPt: usdLimitToPerchTokens(dailyLimitUsd),
|
|
223902
|
+
monthlyLimitPt: usdLimitToPerchTokens(monthlyLimitUsd),
|
|
223903
|
+
dailyCalls: meter?.dailyCalls ?? null,
|
|
223904
|
+
weeklyCalls: meter?.weeklyCalls ?? null,
|
|
223905
|
+
monthlyCalls: meter?.monthlyCalls ?? null,
|
|
223906
|
+
dailyTokens: meter?.dailyTokens ?? null,
|
|
223907
|
+
weeklyTokens: meter?.weeklyTokens ?? null,
|
|
223908
|
+
monthlyTokens: meter?.monthlyTokens ?? null
|
|
223909
|
+
};
|
|
223910
|
+
}
|
|
223911
|
+
function formatInteger(value) {
|
|
223912
|
+
return Math.max(0, Math.round(value ?? 0)).toLocaleString("en-US");
|
|
223913
|
+
}
|
|
223914
|
+
function formatPt(value) {
|
|
223915
|
+
return `${formatInteger(value)} PT`;
|
|
223916
|
+
}
|
|
223917
|
+
function percentUsed(used, limit) {
|
|
223918
|
+
if (limit <= 0) return 0;
|
|
223919
|
+
return Math.max(0, Math.min(used / limit * 100, 100));
|
|
223920
|
+
}
|
|
223921
|
+
function renderTextBar(percent2, width = 24) {
|
|
223922
|
+
const clamped = Math.max(0, Math.min(100, percent2));
|
|
223923
|
+
const filled = Math.round(clamped / 100 * width);
|
|
223924
|
+
return `${"\u2588".repeat(filled)}${"\u2591".repeat(Math.max(0, width - filled))}`;
|
|
223925
|
+
}
|
|
223926
|
+
function formatAllowanceLine(label, usedPt, limitPt, unlimited) {
|
|
223927
|
+
const bar = renderTextBar(unlimited ? 100 : percentUsed(usedPt, limitPt));
|
|
223928
|
+
const amount = unlimited ? `${formatPt(usedPt)} / Unlimited` : `${formatPt(usedPt)} / ${formatPt(limitPt)} \xB7 ${Math.round(percentUsed(usedPt, limitPt))}%`;
|
|
223929
|
+
return `- ${label.padEnd(10)} ${bar} ${amount}`;
|
|
223930
|
+
}
|
|
223931
|
+
function formatUsageAllowanceText(allowance) {
|
|
223932
|
+
const allowanceLabel = allowance.unlimited ? `${allowance.planLabel} \xB7 unlimited allowance` : `${allowance.planLabel} \xB7 ${formatPt(allowance.dailyLimitPt)} daily allowance`;
|
|
223933
|
+
const lines = [
|
|
223934
|
+
"Perch Tokens",
|
|
223935
|
+
`- Plan: ${allowanceLabel}`,
|
|
223936
|
+
formatAllowanceLine("Today", allowance.dailyUsedPt, allowance.dailyLimitPt, allowance.unlimited),
|
|
223937
|
+
formatAllowanceLine("Month", allowance.monthlyUsedPt, allowance.monthlyLimitPt, allowance.unlimited),
|
|
223938
|
+
`- Activity ${formatInteger(allowance.monthlyCalls)} chats this month \xB7 ${formatPt(allowance.weeklyUsedPt)} in 7 days \xB7 ${formatInteger(allowance.weeklyTokens)} model tokens`
|
|
223939
|
+
];
|
|
223940
|
+
return lines.join("\n");
|
|
223941
|
+
}
|
|
223942
|
+
async function fetchUsageAllowanceFromServer(input) {
|
|
223943
|
+
const appUrl = input.cliServerAppUrl?.trim();
|
|
223944
|
+
const token = input.cliServerAccessToken?.trim();
|
|
223945
|
+
if (!appUrl || !token || typeof fetch !== "function") return null;
|
|
223946
|
+
const controller = new AbortController();
|
|
223947
|
+
const timeout = setTimeout(() => controller.abort(), 5e3);
|
|
223948
|
+
try {
|
|
223949
|
+
const response = await fetch(`${appUrl.replace(/\/+$/, "")}/api/perchai/account`, {
|
|
223950
|
+
method: "GET",
|
|
223951
|
+
headers: {
|
|
223952
|
+
Accept: "application/json",
|
|
223953
|
+
Authorization: `Bearer ${token}`
|
|
223954
|
+
},
|
|
223955
|
+
signal: controller.signal
|
|
223956
|
+
});
|
|
223957
|
+
if (!response.ok) return null;
|
|
223958
|
+
const payload = await response.json();
|
|
223959
|
+
if (!payload.ok || !payload.session) return null;
|
|
223960
|
+
return buildUsageAllowanceSnapshot(payload.session, payload.usageMeter ?? null);
|
|
223961
|
+
} catch {
|
|
223962
|
+
return null;
|
|
223963
|
+
} finally {
|
|
223964
|
+
clearTimeout(timeout);
|
|
223965
|
+
}
|
|
223966
|
+
}
|
|
223967
|
+
async function resolveUsageAllowance(input) {
|
|
223968
|
+
if (input.supabase && input.userId && input.workspaceId) {
|
|
223969
|
+
try {
|
|
223970
|
+
const meter = await createUsagePersistence(input.supabase).getUsageMeter({
|
|
223971
|
+
userId: input.userId,
|
|
223972
|
+
workspaceId: input.workspaceId
|
|
223973
|
+
});
|
|
223974
|
+
return buildUsageAllowanceSnapshot(input.sessionContext, meter);
|
|
223975
|
+
} catch {
|
|
223976
|
+
return null;
|
|
223977
|
+
}
|
|
223978
|
+
}
|
|
223979
|
+
const viaServer = await fetchUsageAllowanceFromServer(input);
|
|
223980
|
+
if (viaServer) return viaServer;
|
|
223981
|
+
if (input.userId && input.workspaceId) {
|
|
223982
|
+
return buildUsageAllowanceSnapshot(input.sessionContext, null);
|
|
223983
|
+
}
|
|
223984
|
+
return null;
|
|
223985
|
+
}
|
|
223986
|
+
var init_usageAllowance = __esm({
|
|
223987
|
+
"features/perchTerminal/runtime/usage/usageAllowance.ts"() {
|
|
223988
|
+
"use strict";
|
|
223989
|
+
init_usagePersistence();
|
|
223990
|
+
init_perchTokens();
|
|
223469
223991
|
}
|
|
223470
223992
|
});
|
|
223471
223993
|
|
|
@@ -223515,10 +224037,14 @@ function summarizeInferenceUsageRows(rows, options = {}) {
|
|
|
223515
224037
|
return summary;
|
|
223516
224038
|
}
|
|
223517
224039
|
function formatUsageSummaryText(summary) {
|
|
224040
|
+
const sections = [];
|
|
224041
|
+
if (summary.allowance) {
|
|
224042
|
+
sections.push(formatUsageAllowanceText(summary.allowance));
|
|
224043
|
+
}
|
|
223518
224044
|
const lines = [
|
|
223519
224045
|
"Usage this session",
|
|
223520
|
-
`- Calls: ${
|
|
223521
|
-
`- Tokens: ${
|
|
224046
|
+
`- Calls: ${formatInteger2(summary.calls)}`,
|
|
224047
|
+
`- Tokens: ${formatInteger2(summary.totalTokens)} total (${formatInteger2(summary.promptTokens)} input \xB7 ${formatInteger2(summary.completionTokens)} output${summary.cachedTokens ? ` \xB7 ${formatInteger2(summary.cachedTokens)} cached` : ""})`,
|
|
223522
224048
|
`- Estimated cost: ${formatUsd(summary.estimatedCostUsd)}`
|
|
223523
224049
|
];
|
|
223524
224050
|
if (summary.calls === 0) {
|
|
@@ -223528,11 +224054,12 @@ function formatUsageSummaryText(summary) {
|
|
|
223528
224054
|
lines.push("", "Internal detail:");
|
|
223529
224055
|
for (const row of summary.modelBreakdown.slice(0, 8)) {
|
|
223530
224056
|
lines.push(
|
|
223531
|
-
`- ${row.label}: ${
|
|
224057
|
+
`- ${row.label}: ${formatInteger2(row.totalTokens)} tokens \xB7 ${formatUsd(row.estimatedCostUsd)} \xB7 ${formatInteger2(row.calls)} calls`
|
|
223532
224058
|
);
|
|
223533
224059
|
}
|
|
223534
224060
|
}
|
|
223535
|
-
|
|
224061
|
+
sections.push(lines.join("\n"));
|
|
224062
|
+
return sections.join("\n\n");
|
|
223536
224063
|
}
|
|
223537
224064
|
function buildModelBreakdown(rows) {
|
|
223538
224065
|
const byModel = /* @__PURE__ */ new Map();
|
|
@@ -223568,7 +224095,7 @@ function readNumber(value) {
|
|
|
223568
224095
|
}
|
|
223569
224096
|
return 0;
|
|
223570
224097
|
}
|
|
223571
|
-
function
|
|
224098
|
+
function formatInteger2(value) {
|
|
223572
224099
|
return Math.max(0, Math.round(value)).toLocaleString("en-US");
|
|
223573
224100
|
}
|
|
223574
224101
|
function formatUsd(value) {
|
|
@@ -223578,6 +224105,7 @@ function formatUsd(value) {
|
|
|
223578
224105
|
var init_usageSummary = __esm({
|
|
223579
224106
|
"features/perchTerminal/runtime/usage/usageSummary.ts"() {
|
|
223580
224107
|
"use strict";
|
|
224108
|
+
init_usageAllowance();
|
|
223581
224109
|
}
|
|
223582
224110
|
});
|
|
223583
224111
|
|
|
@@ -223610,7 +224138,11 @@ async function runUsageTurn(input, deps) {
|
|
|
223610
224138
|
recentMessages: input.recentMessages
|
|
223611
224139
|
});
|
|
223612
224140
|
const showModelDetails = canShowPerchDevTools(input.sessionContext.membershipRole);
|
|
223613
|
-
const summary = await
|
|
224141
|
+
const [summary, allowance] = await Promise.all([
|
|
224142
|
+
resolveUsageSummary(input, runIds, showModelDetails),
|
|
224143
|
+
resolveUsageAllowance(input)
|
|
224144
|
+
]);
|
|
224145
|
+
summary.allowance = allowance;
|
|
223614
224146
|
const assistantText = formatUsageSummaryText(summary);
|
|
223615
224147
|
let assistantMessageId = null;
|
|
223616
224148
|
if (input.workspaceId) {
|
|
@@ -223695,6 +224227,7 @@ var init_runUsageTurn = __esm({
|
|
|
223695
224227
|
"features/perchTerminal/runtime/usage/runUsageTurn.ts"() {
|
|
223696
224228
|
"use strict";
|
|
223697
224229
|
init_access();
|
|
224230
|
+
init_usageAllowance();
|
|
223698
224231
|
init_usageSummary();
|
|
223699
224232
|
}
|
|
223700
224233
|
});
|
|
@@ -225085,10 +225618,7 @@ async function runLiveAgentsLoop(input) {
|
|
|
225085
225618
|
const { turn, deps, runId, onEvent } = input;
|
|
225086
225619
|
try {
|
|
225087
225620
|
const loopLane = "chat";
|
|
225088
|
-
const selectedChatModel = resolveModelForLane(
|
|
225089
|
-
turn.founderModelSelection,
|
|
225090
|
-
loopLane
|
|
225091
|
-
);
|
|
225621
|
+
const selectedChatModel = turn.activeContextModel ?? resolveModelForLane(turn.founderModelSelection, loopLane);
|
|
225092
225622
|
const context = input.assembledContext;
|
|
225093
225623
|
if (!context) {
|
|
225094
225624
|
return {
|
|
@@ -230380,6 +230910,7 @@ async function runOperatorTurn(input, deps) {
|
|
|
230380
230910
|
});
|
|
230381
230911
|
try {
|
|
230382
230912
|
const memoryRetriever = buildTurnMemoryRetriever(input);
|
|
230913
|
+
const inputContextModel = input.activeContextModel ?? null;
|
|
230383
230914
|
const memoryContext = await buildMemoryContext({
|
|
230384
230915
|
query: input.trimmedInput,
|
|
230385
230916
|
userId: input.userId ?? (memoryRetriever && input.cliServerAccessToken?.trim() ? "cli_authenticated_user" : null),
|
|
@@ -230387,7 +230918,8 @@ async function runOperatorTurn(input, deps) {
|
|
|
230387
230918
|
threadId: input.threadId,
|
|
230388
230919
|
permanentMemories: input.permanentMemories,
|
|
230389
230920
|
userMemories: input.userMemories,
|
|
230390
|
-
retriever: memoryRetriever
|
|
230921
|
+
retriever: memoryRetriever,
|
|
230922
|
+
contextLimitTokens: inputContextModel ? getEffectiveContextWindow(inputContextModel) : void 0
|
|
230391
230923
|
});
|
|
230392
230924
|
const earlySession = input.threadId ? await loadThreadSession(input.threadId, { supabase: input.supabase ?? null }) : null;
|
|
230393
230925
|
const {
|
|
@@ -230403,10 +230935,7 @@ async function runOperatorTurn(input, deps) {
|
|
|
230403
230935
|
memoryContext,
|
|
230404
230936
|
isSystemNotification
|
|
230405
230937
|
});
|
|
230406
|
-
const chatSelectedModelOption = resolveModelForLane(
|
|
230407
|
-
enrichedInput.founderModelSelection,
|
|
230408
|
-
"chat"
|
|
230409
|
-
);
|
|
230938
|
+
const chatSelectedModelOption = enrichedInput.activeContextModel ?? resolveModelForLane(enrichedInput.founderModelSelection, "chat");
|
|
230410
230939
|
const sources = await prepareTurnSources({ enrichedInput, deps });
|
|
230411
230940
|
const toolDefinitions = prepareTurnToolDefinitions({
|
|
230412
230941
|
enrichedInput,
|
|
@@ -230545,6 +231074,7 @@ var init_runOperatorTurn = __esm({
|
|
|
230545
231074
|
init_liveAgentsLoop();
|
|
230546
231075
|
init_turnAbort();
|
|
230547
231076
|
init_modelRegistry();
|
|
231077
|
+
init_contextThresholds();
|
|
230548
231078
|
init_threadSession();
|
|
230549
231079
|
init_turnMemoryRetriever();
|
|
230550
231080
|
init_turnBootstrap();
|
|
@@ -233519,111 +234049,6 @@ var init_cliAuthSession = __esm({
|
|
|
233519
234049
|
}
|
|
233520
234050
|
});
|
|
233521
234051
|
|
|
233522
|
-
// features/perchTerminal/runtime/cliHost/modelConnection.ts
|
|
233523
|
-
async function connectCliModelProxy(input = {}) {
|
|
233524
|
-
const storedSession = input.storedSession === void 0 ? await readStoredCliAuthSession() : input.storedSession;
|
|
233525
|
-
const usableStoredSession = isStoredCliAuthSessionUsable(storedSession) ? storedSession : null;
|
|
233526
|
-
const appUrl = resolveCliAppUrl(input.appUrl, usableStoredSession?.appUrl ?? null);
|
|
233527
|
-
if (!appUrl) return noCliModelConnection();
|
|
233528
|
-
if (!usableStoredSession?.accessToken) return noCliModelConnection(appUrl);
|
|
233529
|
-
const fetchImpl = input.fetchImpl ?? globalThis.fetch;
|
|
233530
|
-
if (typeof fetchImpl !== "function") return noCliModelConnection(appUrl);
|
|
233531
|
-
const selection = await fetchPublicModelDefaultSelection(
|
|
233532
|
-
appUrl,
|
|
233533
|
-
fetchImpl,
|
|
233534
|
-
usableStoredSession?.accessToken ?? null
|
|
233535
|
-
);
|
|
233536
|
-
if (!selection) return noCliModelConnection(appUrl);
|
|
233537
|
-
const priorProxy = process.env[MODEL_PROXY_ENV];
|
|
233538
|
-
const priorToken = process.env[MODEL_PROXY_TOKEN_ENV];
|
|
233539
|
-
process.env[MODEL_PROXY_ENV] = appUrl;
|
|
233540
|
-
if (usableStoredSession?.accessToken) {
|
|
233541
|
-
process.env[MODEL_PROXY_TOKEN_ENV] = usableStoredSession.accessToken;
|
|
233542
|
-
}
|
|
233543
|
-
return {
|
|
233544
|
-
appUrl,
|
|
233545
|
-
authenticated: !!usableStoredSession?.accessToken,
|
|
233546
|
-
userId: usableStoredSession?.userId ?? null,
|
|
233547
|
-
email: usableStoredSession?.email ?? null,
|
|
233548
|
-
founderModelSelection: selection,
|
|
233549
|
-
restore: () => {
|
|
233550
|
-
if (priorProxy === void 0) {
|
|
233551
|
-
delete process.env[MODEL_PROXY_ENV];
|
|
233552
|
-
} else {
|
|
233553
|
-
process.env[MODEL_PROXY_ENV] = priorProxy;
|
|
233554
|
-
}
|
|
233555
|
-
if (priorToken === void 0) {
|
|
233556
|
-
delete process.env[MODEL_PROXY_TOKEN_ENV];
|
|
233557
|
-
} else {
|
|
233558
|
-
process.env[MODEL_PROXY_TOKEN_ENV] = priorToken;
|
|
233559
|
-
}
|
|
233560
|
-
}
|
|
233561
|
-
};
|
|
233562
|
-
}
|
|
233563
|
-
function resolveCliAppUrl(explicit, stored) {
|
|
233564
|
-
const raw = explicit?.trim() || process.env[CLI_APP_URL_ENV]?.trim() || process.env[FALLBACK_APP_URL_ENV]?.trim() || stored?.trim() || DEFAULT_CLI_APP_URL;
|
|
233565
|
-
if (!raw) return null;
|
|
233566
|
-
const withProtocol = /^https?:\/\//i.test(raw) ? raw : `http://${raw}`;
|
|
233567
|
-
try {
|
|
233568
|
-
const url = new URL(withProtocol);
|
|
233569
|
-
url.pathname = url.pathname.replace(/\/+$/, "");
|
|
233570
|
-
url.search = "";
|
|
233571
|
-
url.hash = "";
|
|
233572
|
-
return url.toString().replace(/\/+$/, "");
|
|
233573
|
-
} catch {
|
|
233574
|
-
return null;
|
|
233575
|
-
}
|
|
233576
|
-
}
|
|
233577
|
-
async function fetchPublicModelDefaultSelection(appUrl, fetchImpl, accessToken) {
|
|
233578
|
-
const url = `${appUrl}/api/perch-terminal/public-model-default`;
|
|
233579
|
-
const controller = new AbortController();
|
|
233580
|
-
const timeout = setTimeout(() => controller.abort(), 3500);
|
|
233581
|
-
try {
|
|
233582
|
-
const response = await fetchImpl(url, {
|
|
233583
|
-
method: "GET",
|
|
233584
|
-
headers: {
|
|
233585
|
-
Accept: "application/json",
|
|
233586
|
-
...accessToken ? { Authorization: `Bearer ${accessToken}` } : {}
|
|
233587
|
-
},
|
|
233588
|
-
signal: controller.signal
|
|
233589
|
-
});
|
|
233590
|
-
if (!response.ok) return null;
|
|
233591
|
-
const body = await response.json();
|
|
233592
|
-
if (!body || typeof body !== "object") return null;
|
|
233593
|
-
const record = body;
|
|
233594
|
-
if (record.ok !== true) return null;
|
|
233595
|
-
return parsePublicModelDefaultPayload({ selection: record.selection }).selection;
|
|
233596
|
-
} catch {
|
|
233597
|
-
return null;
|
|
233598
|
-
} finally {
|
|
233599
|
-
clearTimeout(timeout);
|
|
233600
|
-
}
|
|
233601
|
-
}
|
|
233602
|
-
function noCliModelConnection(appUrl = null) {
|
|
233603
|
-
return {
|
|
233604
|
-
appUrl,
|
|
233605
|
-
authenticated: false,
|
|
233606
|
-
userId: null,
|
|
233607
|
-
email: null,
|
|
233608
|
-
founderModelSelection: null,
|
|
233609
|
-
restore: () => {
|
|
233610
|
-
}
|
|
233611
|
-
};
|
|
233612
|
-
}
|
|
233613
|
-
var MODEL_PROXY_ENV, MODEL_PROXY_TOKEN_ENV, CLI_APP_URL_ENV, FALLBACK_APP_URL_ENV, DEFAULT_CLI_APP_URL;
|
|
233614
|
-
var init_modelConnection = __esm({
|
|
233615
|
-
"features/perchTerminal/runtime/cliHost/modelConnection.ts"() {
|
|
233616
|
-
"use strict";
|
|
233617
|
-
init_publicModelDefault();
|
|
233618
|
-
init_cliAuthSession();
|
|
233619
|
-
MODEL_PROXY_ENV = "PERCH_MODEL_CALL_PROXY_URL";
|
|
233620
|
-
MODEL_PROXY_TOKEN_ENV = "PERCH_MODEL_CALL_PROXY_TOKEN";
|
|
233621
|
-
CLI_APP_URL_ENV = "PERCH_CLI_APP_URL";
|
|
233622
|
-
FALLBACK_APP_URL_ENV = "PERCH_APP_URL";
|
|
233623
|
-
DEFAULT_CLI_APP_URL = "https://app.perchai.app";
|
|
233624
|
-
}
|
|
233625
|
-
});
|
|
233626
|
-
|
|
233627
234052
|
// features/perchTerminal/runtime/cliHost/cliStandaloneOAuth.ts
|
|
233628
234053
|
import { execFile as execFile2 } from "node:child_process";
|
|
233629
234054
|
import http from "node:http";
|
|
@@ -233672,7 +234097,8 @@ async function runCliStandaloneOAuthLogin(input) {
|
|
|
233672
234097
|
provider,
|
|
233673
234098
|
options: {
|
|
233674
234099
|
redirectTo: callback.redirectTo,
|
|
233675
|
-
skipBrowserRedirect: true
|
|
234100
|
+
skipBrowserRedirect: true,
|
|
234101
|
+
data: { signup_source: "cli" }
|
|
233676
234102
|
}
|
|
233677
234103
|
});
|
|
233678
234104
|
if (error || !data.url) {
|
|
@@ -233831,6 +234257,166 @@ var init_cliStandaloneOAuth = __esm({
|
|
|
233831
234257
|
}
|
|
233832
234258
|
});
|
|
233833
234259
|
|
|
234260
|
+
// features/perchTerminal/runtime/cliHost/cliAuthRefresh.ts
|
|
234261
|
+
async function ensureFreshCliAuthSession(input) {
|
|
234262
|
+
const session = input.session;
|
|
234263
|
+
if (!session?.accessToken?.trim()) return null;
|
|
234264
|
+
const nowSeconds = Math.floor(Date.now() / 1e3);
|
|
234265
|
+
const stillUsable = !session.expiresAt || session.expiresAt > nowSeconds + 90;
|
|
234266
|
+
if (stillUsable) return session;
|
|
234267
|
+
if (!session.refreshToken?.trim()) return null;
|
|
234268
|
+
const fetchImpl = input.fetchImpl ?? globalThis.fetch;
|
|
234269
|
+
if (typeof fetchImpl !== "function") return null;
|
|
234270
|
+
const appUrl = session.appUrl?.trim();
|
|
234271
|
+
if (!appUrl) return null;
|
|
234272
|
+
const config = await fetchCliAuthConfig(appUrl, fetchImpl).catch(() => ({ ok: false }));
|
|
234273
|
+
if (!config.ok || !config.supabaseUrl || !config.supabaseAnonKey) return null;
|
|
234274
|
+
const supabase = createClient(config.supabaseUrl, config.supabaseAnonKey, {
|
|
234275
|
+
auth: {
|
|
234276
|
+
autoRefreshToken: false,
|
|
234277
|
+
detectSessionInUrl: false,
|
|
234278
|
+
persistSession: false
|
|
234279
|
+
}
|
|
234280
|
+
});
|
|
234281
|
+
try {
|
|
234282
|
+
const { data, error } = await supabase.auth.refreshSession({
|
|
234283
|
+
refresh_token: session.refreshToken
|
|
234284
|
+
});
|
|
234285
|
+
if (error || !data.session) return null;
|
|
234286
|
+
const refreshed = {
|
|
234287
|
+
version: 1,
|
|
234288
|
+
appUrl: session.appUrl,
|
|
234289
|
+
accessToken: data.session.access_token,
|
|
234290
|
+
refreshToken: data.session.refresh_token ?? session.refreshToken,
|
|
234291
|
+
expiresAt: data.session.expires_at ?? null,
|
|
234292
|
+
userId: data.session.user?.id ?? session.userId ?? null,
|
|
234293
|
+
email: data.session.user?.email ?? session.email ?? null,
|
|
234294
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
234295
|
+
};
|
|
234296
|
+
await writeStoredCliAuthSession(refreshed);
|
|
234297
|
+
return refreshed;
|
|
234298
|
+
} catch {
|
|
234299
|
+
return null;
|
|
234300
|
+
}
|
|
234301
|
+
}
|
|
234302
|
+
var init_cliAuthRefresh = __esm({
|
|
234303
|
+
"features/perchTerminal/runtime/cliHost/cliAuthRefresh.ts"() {
|
|
234304
|
+
"use strict";
|
|
234305
|
+
init_dist4();
|
|
234306
|
+
init_cliStandaloneOAuth();
|
|
234307
|
+
init_cliAuthSession();
|
|
234308
|
+
}
|
|
234309
|
+
});
|
|
234310
|
+
|
|
234311
|
+
// features/perchTerminal/runtime/cliHost/modelConnection.ts
|
|
234312
|
+
async function connectCliModelProxy(input = {}) {
|
|
234313
|
+
const storedSession = input.storedSession === void 0 ? await readStoredCliAuthSession() : input.storedSession;
|
|
234314
|
+
const usableStoredSession = await ensureFreshCliAuthSession({
|
|
234315
|
+
session: storedSession,
|
|
234316
|
+
fetchImpl: input.fetchImpl
|
|
234317
|
+
});
|
|
234318
|
+
const appUrl = resolveCliAppUrl(input.appUrl, usableStoredSession?.appUrl ?? null);
|
|
234319
|
+
if (!appUrl) return noCliModelConnection();
|
|
234320
|
+
if (!usableStoredSession?.accessToken) return noCliModelConnection(appUrl);
|
|
234321
|
+
const fetchImpl = input.fetchImpl ?? globalThis.fetch;
|
|
234322
|
+
if (typeof fetchImpl !== "function") return noCliModelConnection(appUrl);
|
|
234323
|
+
const selection = await fetchPublicModelDefaultSelection(
|
|
234324
|
+
appUrl,
|
|
234325
|
+
fetchImpl,
|
|
234326
|
+
usableStoredSession?.accessToken ?? null
|
|
234327
|
+
);
|
|
234328
|
+
if (!selection) return noCliModelConnection(appUrl);
|
|
234329
|
+
const priorProxy = process.env[MODEL_PROXY_ENV];
|
|
234330
|
+
const priorToken = process.env[MODEL_PROXY_TOKEN_ENV];
|
|
234331
|
+
process.env[MODEL_PROXY_ENV] = appUrl;
|
|
234332
|
+
if (usableStoredSession?.accessToken) {
|
|
234333
|
+
process.env[MODEL_PROXY_TOKEN_ENV] = usableStoredSession.accessToken;
|
|
234334
|
+
}
|
|
234335
|
+
return {
|
|
234336
|
+
appUrl,
|
|
234337
|
+
authenticated: !!usableStoredSession?.accessToken,
|
|
234338
|
+
userId: usableStoredSession?.userId ?? null,
|
|
234339
|
+
email: usableStoredSession?.email ?? null,
|
|
234340
|
+
founderModelSelection: selection,
|
|
234341
|
+
restore: () => {
|
|
234342
|
+
if (priorProxy === void 0) {
|
|
234343
|
+
delete process.env[MODEL_PROXY_ENV];
|
|
234344
|
+
} else {
|
|
234345
|
+
process.env[MODEL_PROXY_ENV] = priorProxy;
|
|
234346
|
+
}
|
|
234347
|
+
if (priorToken === void 0) {
|
|
234348
|
+
delete process.env[MODEL_PROXY_TOKEN_ENV];
|
|
234349
|
+
} else {
|
|
234350
|
+
process.env[MODEL_PROXY_TOKEN_ENV] = priorToken;
|
|
234351
|
+
}
|
|
234352
|
+
}
|
|
234353
|
+
};
|
|
234354
|
+
}
|
|
234355
|
+
function resolveCliAppUrl(explicit, stored) {
|
|
234356
|
+
const raw = explicit?.trim() || process.env[CLI_APP_URL_ENV]?.trim() || process.env[FALLBACK_APP_URL_ENV]?.trim() || stored?.trim() || DEFAULT_CLI_APP_URL;
|
|
234357
|
+
if (!raw) return null;
|
|
234358
|
+
const withProtocol = /^https?:\/\//i.test(raw) ? raw : `http://${raw}`;
|
|
234359
|
+
try {
|
|
234360
|
+
const url = new URL(withProtocol);
|
|
234361
|
+
url.pathname = url.pathname.replace(/\/+$/, "");
|
|
234362
|
+
url.search = "";
|
|
234363
|
+
url.hash = "";
|
|
234364
|
+
return url.toString().replace(/\/+$/, "");
|
|
234365
|
+
} catch {
|
|
234366
|
+
return null;
|
|
234367
|
+
}
|
|
234368
|
+
}
|
|
234369
|
+
async function fetchPublicModelDefaultSelection(appUrl, fetchImpl, accessToken) {
|
|
234370
|
+
const url = `${appUrl}/api/perch-terminal/public-model-default`;
|
|
234371
|
+
const controller = new AbortController();
|
|
234372
|
+
const timeout = setTimeout(() => controller.abort(), 3500);
|
|
234373
|
+
try {
|
|
234374
|
+
const response = await fetchImpl(url, {
|
|
234375
|
+
method: "GET",
|
|
234376
|
+
headers: {
|
|
234377
|
+
Accept: "application/json",
|
|
234378
|
+
...accessToken ? { Authorization: `Bearer ${accessToken}` } : {}
|
|
234379
|
+
},
|
|
234380
|
+
signal: controller.signal
|
|
234381
|
+
});
|
|
234382
|
+
if (!response.ok) return null;
|
|
234383
|
+
const body = await response.json();
|
|
234384
|
+
if (!body || typeof body !== "object") return null;
|
|
234385
|
+
const record = body;
|
|
234386
|
+
if (record.ok !== true) return null;
|
|
234387
|
+
return parsePublicModelDefaultPayload({ selection: record.selection }).selection;
|
|
234388
|
+
} catch {
|
|
234389
|
+
return null;
|
|
234390
|
+
} finally {
|
|
234391
|
+
clearTimeout(timeout);
|
|
234392
|
+
}
|
|
234393
|
+
}
|
|
234394
|
+
function noCliModelConnection(appUrl = null) {
|
|
234395
|
+
return {
|
|
234396
|
+
appUrl,
|
|
234397
|
+
authenticated: false,
|
|
234398
|
+
userId: null,
|
|
234399
|
+
email: null,
|
|
234400
|
+
founderModelSelection: null,
|
|
234401
|
+
restore: () => {
|
|
234402
|
+
}
|
|
234403
|
+
};
|
|
234404
|
+
}
|
|
234405
|
+
var MODEL_PROXY_ENV, MODEL_PROXY_TOKEN_ENV, CLI_APP_URL_ENV, FALLBACK_APP_URL_ENV, DEFAULT_CLI_APP_URL;
|
|
234406
|
+
var init_modelConnection = __esm({
|
|
234407
|
+
"features/perchTerminal/runtime/cliHost/modelConnection.ts"() {
|
|
234408
|
+
"use strict";
|
|
234409
|
+
init_publicModelDefault();
|
|
234410
|
+
init_cliAuthSession();
|
|
234411
|
+
init_cliAuthRefresh();
|
|
234412
|
+
MODEL_PROXY_ENV = "PERCH_MODEL_CALL_PROXY_URL";
|
|
234413
|
+
MODEL_PROXY_TOKEN_ENV = "PERCH_MODEL_CALL_PROXY_TOKEN";
|
|
234414
|
+
CLI_APP_URL_ENV = "PERCH_CLI_APP_URL";
|
|
234415
|
+
FALLBACK_APP_URL_ENV = "PERCH_APP_URL";
|
|
234416
|
+
DEFAULT_CLI_APP_URL = "https://app.perchai.app";
|
|
234417
|
+
}
|
|
234418
|
+
});
|
|
234419
|
+
|
|
233834
234420
|
// lib/perchTerminal/statusLabels.ts
|
|
233835
234421
|
function sectionLabel(sectionKey) {
|
|
233836
234422
|
if (STATUS_LABELS[sectionKey]) return STATUS_LABELS[sectionKey];
|
|
@@ -290330,6 +290916,27 @@ async function runInteractiveSlashCommand(input) {
|
|
|
290330
290916
|
input.state.personaId = parsed.value;
|
|
290331
290917
|
writeModeLine(input.writer, "persona", input.state.personaId);
|
|
290332
290918
|
return "continue";
|
|
290919
|
+
case "model": {
|
|
290920
|
+
const labelFor = (choice) => choice === "internal" ? "Internal" : ROOST_TIER_LABELS[choice];
|
|
290921
|
+
if (!parsed.value) {
|
|
290922
|
+
writeModeLine(input.writer, "model", labelFor(input.state.roostChoice));
|
|
290923
|
+
return "continue";
|
|
290924
|
+
}
|
|
290925
|
+
input.state.roostChoice = parsed.value;
|
|
290926
|
+
setRoostUserSelectionForNode({ choice: parsed.value, reasoningEnabled: input.state.roostReasoningEnabled });
|
|
290927
|
+
writeModeLine(input.writer, "model", labelFor(parsed.value));
|
|
290928
|
+
return "continue";
|
|
290929
|
+
}
|
|
290930
|
+
case "thinking": {
|
|
290931
|
+
if (parsed.value === void 0) {
|
|
290932
|
+
writeModeLine(input.writer, "thinking", input.state.roostReasoningEnabled ? "on" : "off");
|
|
290933
|
+
return "continue";
|
|
290934
|
+
}
|
|
290935
|
+
input.state.roostReasoningEnabled = parsed.value;
|
|
290936
|
+
setRoostUserSelectionForNode({ choice: input.state.roostChoice, reasoningEnabled: parsed.value });
|
|
290937
|
+
writeModeLine(input.writer, "thinking", input.state.roostReasoningEnabled ? "on" : "off");
|
|
290938
|
+
return "continue";
|
|
290939
|
+
}
|
|
290333
290940
|
case "appUrl":
|
|
290334
290941
|
if (!parsed.value) {
|
|
290335
290942
|
writeModeLine(input.writer, "app-url", input.state.appUrl ?? "(none)");
|
|
@@ -290423,6 +291030,22 @@ function parseInteractiveSlashCommand(input) {
|
|
|
290423
291030
|
if (!value) return { ok: true, kind: "persona" };
|
|
290424
291031
|
if (!isPersonaId(value)) return { ok: false, error: `Unknown persona: ${value}` };
|
|
290425
291032
|
return { ok: true, kind: "persona", value };
|
|
291033
|
+
case "model":
|
|
291034
|
+
if (!value) return { ok: true, kind: "model" };
|
|
291035
|
+
{
|
|
291036
|
+
const normalized = value.toLowerCase().replace(/[\s-]+/g, "_");
|
|
291037
|
+
const choice = normalizeRoostModelChoice(
|
|
291038
|
+
normalized === "standardmax" ? "standard_max" : normalized === "promax" ? "pro_max" : normalized
|
|
291039
|
+
);
|
|
291040
|
+
if (!choice) {
|
|
291041
|
+
return { ok: false, error: `Unknown model: ${value}. Try standard, standard max, pro, pro max, or internal.` };
|
|
291042
|
+
}
|
|
291043
|
+
return { ok: true, kind: "model", value: choice };
|
|
291044
|
+
}
|
|
291045
|
+
case "thinking":
|
|
291046
|
+
if (!value) return { ok: true, kind: "thinking" };
|
|
291047
|
+
if (value !== "on" && value !== "off") return { ok: false, error: "/thinking expects on or off." };
|
|
291048
|
+
return { ok: true, kind: "thinking", value: value === "on" };
|
|
290426
291049
|
case "app-url":
|
|
290427
291050
|
case "app":
|
|
290428
291051
|
return { ok: true, kind: "appUrl", ...value ? { value } : {} };
|
|
@@ -290463,6 +291086,8 @@ function renderInteractiveStatus(state, connection, session, workspaceId) {
|
|
|
290463
291086
|
["permission", state.permissionMode],
|
|
290464
291087
|
["mode", state.chatMode],
|
|
290465
291088
|
["persona", state.personaId],
|
|
291089
|
+
["model", state.roostChoice === "internal" ? "Internal" : ROOST_TIER_LABELS[state.roostChoice]],
|
|
291090
|
+
["thinking", state.roostReasoningEnabled ? "on" : "off"],
|
|
290466
291091
|
["thread", state.threadId],
|
|
290467
291092
|
["context", renderCliContextMeter(state.contextSnapshot, activeContextModel)],
|
|
290468
291093
|
["saved", state.persistedThreadUpdatedAt ? new Date(state.persistedThreadUpdatedAt).toLocaleString() : "(new thread)"],
|
|
@@ -290602,11 +291227,13 @@ function renderInkSpeakerLabel(label) {
|
|
|
290602
291227
|
return `${label}\u203A`;
|
|
290603
291228
|
}
|
|
290604
291229
|
function createInteractiveCliState(options) {
|
|
290605
|
-
|
|
291230
|
+
const state = {
|
|
290606
291231
|
cwd: resolveExistingDirectory(options.cwd ?? process.cwd()),
|
|
290607
291232
|
chatMode: options.chatMode ?? "agents",
|
|
290608
291233
|
personaId: options.personaId ?? "saffron",
|
|
290609
291234
|
permissionMode: options.permissionMode ?? "default",
|
|
291235
|
+
roostChoice: "internal",
|
|
291236
|
+
roostReasoningEnabled: true,
|
|
290610
291237
|
threadId: options.threadId?.trim() || "cli-default",
|
|
290611
291238
|
threadScopeKey: null,
|
|
290612
291239
|
desktopConnected: options.desktopConnected ?? false,
|
|
@@ -290617,6 +291244,11 @@ function createInteractiveCliState(options) {
|
|
|
290617
291244
|
contextSnapshot: null,
|
|
290618
291245
|
persistedThreadUpdatedAt: null
|
|
290619
291246
|
};
|
|
291247
|
+
setRoostUserSelectionForNode({
|
|
291248
|
+
choice: state.roostChoice,
|
|
291249
|
+
reasoningEnabled: state.roostReasoningEnabled
|
|
291250
|
+
});
|
|
291251
|
+
return state;
|
|
290620
291252
|
}
|
|
290621
291253
|
async function hydrateInteractiveCliState(state) {
|
|
290622
291254
|
const persisted = await hydrateCliThreadState(state.threadId, state.threadScopeKey);
|
|
@@ -291675,6 +292307,8 @@ var init_perch_cli = __esm({
|
|
|
291675
292307
|
init_perchCore();
|
|
291676
292308
|
init_cliHost();
|
|
291677
292309
|
init_modelConnection();
|
|
292310
|
+
init_roost();
|
|
292311
|
+
init_roostUserSelectionClient();
|
|
291678
292312
|
init_cliAuthSession();
|
|
291679
292313
|
init_cliStandaloneOAuth();
|
|
291680
292314
|
init_contextMeterDisplay();
|
|
@@ -291750,7 +292384,9 @@ Commands:
|
|
|
291750
292384
|
/help Show this list.
|
|
291751
292385
|
/status Show cwd, auth, mode, persona, permission, and thread.
|
|
291752
292386
|
/skills [name] List Perch core skills, or show one skill body.
|
|
291753
|
-
/usage Show
|
|
292387
|
+
/usage Show Perch Token allowance and session usage.
|
|
292388
|
+
/model [standard|standard max|pro|pro max|internal] Show or set your model.
|
|
292389
|
+
/thinking [on|off] Show or toggle Thinking for the selected model.
|
|
291754
292390
|
/cwd [dir] Show or change the working directory.
|
|
291755
292391
|
/permission [mode] Show or set default, auto_review, take_the_wheel, or plan.
|
|
291756
292392
|
/permissions [mode] Alias for /permission.
|
|
@@ -291812,8 +292448,10 @@ Commands:
|
|
|
291812
292448
|
];
|
|
291813
292449
|
PERCH_SPLASH_COMMANDS = [
|
|
291814
292450
|
["/status", "show auth, route, tools, and thread"],
|
|
291815
|
-
["/usage", "show
|
|
292451
|
+
["/usage", "show Perch Token allowance and session usage"],
|
|
291816
292452
|
["/skills", "show reusable operator skills"],
|
|
292453
|
+
["/model", "choose Standard, Standard Max, Pro, or Pro Max"],
|
|
292454
|
+
["/thinking", "toggle model thinking"],
|
|
291817
292455
|
["/persona", "swap saffron or quill"],
|
|
291818
292456
|
["/permission", "change autonomy for the next turns"],
|
|
291819
292457
|
["/login", "connect your Perch account"]
|