@sayknow-cli/coding-agent 0.6.6 → 0.6.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/dist/types/config/settings-schema.d.ts +79 -0
- package/dist/types/i18n/messages/en.d.ts +2 -0
- package/dist/types/modes/components/welcome.d.ts +21 -4
- package/dist/types/modes/interactive-mode.d.ts +2 -5
- package/dist/types/modes/types.d.ts +2 -0
- package/dist/types/sdk/broker/broker.d.ts +22 -0
- package/dist/types/sdk/broker/process-guard.d.ts +71 -0
- package/dist/types/sdk/broker/transport.d.ts +2 -0
- package/dist/types/sdk/bus/chat-daemon-runtime.d.ts +4 -0
- package/dist/types/session/agent-session.d.ts +9 -0
- package/dist/types/session/auth-storage-discovery.d.ts +15 -0
- package/dist/types/session/auto-fallback.d.ts +27 -0
- package/dist/types/session/fallback-chain-controller.d.ts +5 -0
- package/dist/types/session/response-language.d.ts +25 -0
- package/dist/types/setup/model-onboarding-guidance.d.ts +8 -1
- package/dist/types/setup/provider-onboarding.d.ts +2 -0
- package/dist/types/tools/index.d.ts +1 -0
- package/dist/types/tools/locate-core.d.ts +97 -0
- package/dist/types/tools/locate.d.ts +44 -0
- package/package.json +7 -7
- package/scripts/generate-sdk-operation-inventory.ts +4 -0
- package/src/cli/setup-cli.ts +7 -4
- package/src/commands/sdk.ts +3 -0
- package/src/commands/setup.ts +4 -1
- package/src/config/settings-schema.ts +82 -0
- package/src/decisions/typesafe-backend.ts +38 -4
- package/src/i18n/messages/de.settings.ts +26 -0
- package/src/i18n/messages/de.ts +2 -0
- package/src/i18n/messages/en.ts +2 -0
- package/src/i18n/messages/es.settings.ts +26 -0
- package/src/i18n/messages/es.ts +2 -0
- package/src/i18n/messages/fr.settings.ts +26 -0
- package/src/i18n/messages/fr.ts +2 -0
- package/src/i18n/messages/ja.settings.ts +26 -0
- package/src/i18n/messages/ja.ts +2 -0
- package/src/i18n/messages/ko.settings.ts +25 -0
- package/src/i18n/messages/ko.ts +2 -0
- package/src/i18n/messages/zh.settings.ts +23 -0
- package/src/i18n/messages/zh.ts +2 -0
- package/src/internal-urls/docs-index.generated.ts +7 -6
- package/src/modes/components/welcome.ts +241 -68
- package/src/modes/controllers/input-controller.ts +2 -0
- package/src/modes/controllers/selector-controller.ts +13 -0
- package/src/modes/interactive-mode.ts +123 -14
- package/src/modes/types.ts +2 -0
- package/src/prompts/system/system-prompt.md +7 -2
- package/src/prompts/tools/locate.md +12 -0
- package/src/sdk/broker/broker.ts +75 -1
- package/src/sdk/broker/process-guard.ts +160 -0
- package/src/sdk/broker/transport.ts +15 -1
- package/src/sdk/bus/chat-daemon-runtime.ts +13 -1
- package/src/sdk/protocol/operation-inventory.generated.json +22 -0
- package/src/sdk/session.ts +4 -1
- package/src/session/agent-session.ts +118 -2
- package/src/session/auth-storage-discovery.ts +22 -7
- package/src/session/auto-fallback.ts +59 -0
- package/src/session/fallback-chain-controller.ts +5 -0
- package/src/session/response-language.ts +71 -0
- package/src/setup/model-onboarding-guidance.ts +29 -14
- package/src/setup/provider-onboarding.ts +5 -0
- package/src/slash-commands/builtin-registry.ts +112 -2
- package/src/tools/index.ts +3 -0
- package/src/tools/locate-core.ts +720 -0
- package/src/tools/locate.ts +203 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { AgentTool, AgentToolResult } from "@sayknow-cli/agent-core";
|
|
2
|
+
import * as z from "zod/v4";
|
|
3
|
+
import type { ToolSession } from ".";
|
|
4
|
+
import { type LocateResult } from "./locate-core";
|
|
5
|
+
declare const locateSchema: z.ZodObject<{
|
|
6
|
+
query: z.ZodString;
|
|
7
|
+
path: z.ZodOptional<z.ZodString>;
|
|
8
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
type LocateParams = z.infer<typeof locateSchema>;
|
|
11
|
+
export interface LocateToolDetails {
|
|
12
|
+
result: Omit<LocateResult, "files" | "weakLeads"> & {
|
|
13
|
+
files: string[];
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export declare class LocateTool implements AgentTool<typeof locateSchema, LocateToolDetails> {
|
|
17
|
+
private readonly session;
|
|
18
|
+
readonly name = "locate";
|
|
19
|
+
readonly label = "Locate";
|
|
20
|
+
readonly summary = "Find code by describing what it does (Jev relevance judgement)";
|
|
21
|
+
/**
|
|
22
|
+
* Essential when offered: its value is being picked instead of a grep, which a
|
|
23
|
+
* discoverable tool hidden behind search_tool_bm25 would rarely be. createIf already
|
|
24
|
+
* keeps it out unless a TypeSafe key is stored.
|
|
25
|
+
*/
|
|
26
|
+
readonly loadMode = "essential";
|
|
27
|
+
readonly description: string;
|
|
28
|
+
readonly parameters: z.ZodObject<{
|
|
29
|
+
query: z.ZodString;
|
|
30
|
+
path: z.ZodOptional<z.ZodString>;
|
|
31
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
32
|
+
}, z.core.$strip>;
|
|
33
|
+
readonly strict = true;
|
|
34
|
+
/**
|
|
35
|
+
* Offered only when it can work: a TypeSafe key is stored and `locate.enabled` is on.
|
|
36
|
+
* Without the hosted model every judgement would fall to an uncalibrated LLM, one
|
|
37
|
+
* request per folder batch, which costs more than the search saves.
|
|
38
|
+
*/
|
|
39
|
+
static createIf(session: ToolSession): LocateTool | null;
|
|
40
|
+
constructor(session: ToolSession);
|
|
41
|
+
execute(_toolCallId: string, params: LocateParams, signal?: AbortSignal): Promise<AgentToolResult<LocateToolDetails>>;
|
|
42
|
+
}
|
|
43
|
+
export declare function formatLocateResult(query: string, root: string, cwd: string, result: LocateResult): string;
|
|
44
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@sayknow-cli/coding-agent",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.8",
|
|
5
5
|
"description": "Sayknow-CLI CLI with read, bash, edit, write tools and session management",
|
|
6
6
|
"homepage": "https://sayknow-cli.com",
|
|
7
7
|
"author": "jaybeyond",
|
|
@@ -54,12 +54,12 @@
|
|
|
54
54
|
"@agentclientprotocol/sdk": "1.3.0",
|
|
55
55
|
"@babel/parser": "^7.29.3",
|
|
56
56
|
"@mozilla/readability": "^0.6.0",
|
|
57
|
-
"@sayknow-cli/stats": "0.6.
|
|
58
|
-
"@sayknow-cli/agent-core": "0.6.
|
|
59
|
-
"@sayknow-cli/ai": "0.6.
|
|
60
|
-
"@sayknow-cli/natives": "0.6.
|
|
61
|
-
"@sayknow-cli/tui": "0.6.
|
|
62
|
-
"@sayknow-cli/utils": "0.6.
|
|
57
|
+
"@sayknow-cli/stats": "0.6.8",
|
|
58
|
+
"@sayknow-cli/agent-core": "0.6.8",
|
|
59
|
+
"@sayknow-cli/ai": "0.6.8",
|
|
60
|
+
"@sayknow-cli/natives": "0.6.8",
|
|
61
|
+
"@sayknow-cli/tui": "0.6.8",
|
|
62
|
+
"@sayknow-cli/utils": "0.6.8",
|
|
63
63
|
"@puppeteer/browsers": "^2.13.0",
|
|
64
64
|
"@types/turndown": "5.0.6",
|
|
65
65
|
"@xterm/headless": "^6.0.0",
|
|
@@ -38,6 +38,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
|
|
|
38
38
|
"local session-discovery metadata command; no SDK operation counterpart or runtime/retention authority",
|
|
39
39
|
"slash_command:unstar":
|
|
40
40
|
"local session-discovery metadata command; no SDK operation counterpart or runtime/retention authority",
|
|
41
|
+
"slash_command:fallback":
|
|
42
|
+
"local fallback-chain configuration (fallback.models / fallback.auto settings); no SDK operation counterpart, and SDK clients observe switches via model_fallback_switched",
|
|
41
43
|
"slash_command:import-session":
|
|
42
44
|
"local transcript-file import into a new session; ACP is explicitly disabled and no SDK operation reads caller-selected host paths",
|
|
43
45
|
"agent_session:constructor": "internal accessor/plumbing, not a user-facing control seam",
|
|
@@ -193,6 +195,8 @@ const LOCKED_EXCLUSIONS: Readonly<Record<string, string>> = {
|
|
|
193
195
|
"internal profile and fallback-chain state, not a user-facing SDK control seam",
|
|
194
196
|
"agent_session:setConfiguredModelChain":
|
|
195
197
|
"internal profile and fallback-chain state, not a user-facing SDK control seam",
|
|
198
|
+
"agent_session:getDefaultFallbackChain":
|
|
199
|
+
"internal profile and fallback-chain state, not a user-facing SDK control seam",
|
|
196
200
|
"agent_session:setDefaultFallbackRuntimeModel":
|
|
197
201
|
"internal fallback runtime bookkeeping, not a user-facing SDK control seam",
|
|
198
202
|
"agent_session:seedDefaultFallbackResolution":
|
package/src/cli/setup-cli.ts
CHANGED
|
@@ -33,8 +33,10 @@ import {
|
|
|
33
33
|
import { buildHostPluginSetup, formatHostPluginSetup, type HostPluginKind } from "../setup/host-plugin-setup";
|
|
34
34
|
import {
|
|
35
35
|
addApiCompatibleProvider,
|
|
36
|
+
formatProviderPresetChoices,
|
|
36
37
|
formatProviderPresetList,
|
|
37
38
|
formatProviderSetupResult,
|
|
39
|
+
PROVIDER_PRESETS,
|
|
38
40
|
parseProviderCompatibility,
|
|
39
41
|
} from "../setup/provider-onboarding";
|
|
40
42
|
|
|
@@ -119,7 +121,7 @@ function rejectProviderFlagsOutsideProvider(component: SetupComponent, flags: Se
|
|
|
119
121
|
console.error(chalk.red("Provider setup flags require the explicit `provider` component."));
|
|
120
122
|
console.error(
|
|
121
123
|
chalk.dim(
|
|
122
|
-
`Run: ${APP_NAME} setup provider --preset
|
|
124
|
+
`Run: ${APP_NAME} setup provider --preset <${formatProviderPresetChoices()}> or ${APP_NAME} setup provider --compat <openai|anthropic> --provider <id> --base-url <url> --api-key-env <ENV> --model <id>`,
|
|
123
125
|
),
|
|
124
126
|
);
|
|
125
127
|
process.exit(1);
|
|
@@ -761,8 +763,9 @@ ${chalk.bold("Components:")}
|
|
|
761
763
|
|
|
762
764
|
|
|
763
765
|
${chalk.bold("Provider example:")}
|
|
764
|
-
|
|
765
|
-
${APP_NAME} setup provider --preset
|
|
766
|
+
${PROVIDER_PRESETS.slice(0, 2)
|
|
767
|
+
.map(preset => ` ${APP_NAME} setup provider --preset ${preset.id}`)
|
|
768
|
+
.join("\n")}
|
|
766
769
|
MY_PROVIDER_KEY=sk-... ${APP_NAME} setup provider --compat openai --provider my-oai --base-url https://api.example.com/v1 --api-key-env MY_PROVIDER_KEY --model gpt-example
|
|
767
770
|
|
|
768
771
|
${chalk.bold("Hermes example:")}
|
|
@@ -775,7 +778,7 @@ ${chalk.bold("Options:")}
|
|
|
775
778
|
-c, --check Check if dependencies are installed without installing
|
|
776
779
|
-f, --force Overwrite existing default workflow skill files
|
|
777
780
|
--json Output status as JSON
|
|
778
|
-
--preset Provider preset:
|
|
781
|
+
--preset Provider preset: ${PROVIDER_PRESETS.map(preset => preset.id).join(", ")} (aliases: ${PROVIDER_PRESETS.flatMap(preset => preset.aliases).join(", ")})
|
|
779
782
|
--compat Provider compatibility: openai or anthropic
|
|
780
783
|
--provider Provider id to add to models.yml
|
|
781
784
|
--base-url Provider API base URL
|
package/src/commands/sdk.ts
CHANGED
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
writeSessionLifecycleFailure,
|
|
19
19
|
writeSessionLifecycleReady,
|
|
20
20
|
} from "../sdk/broker/lifecycle";
|
|
21
|
+
import { exitIfSourceGone, startSessionHostGuard } from "../sdk/broker/process-guard";
|
|
21
22
|
import { processIncarnation } from "../sdk/broker/process-incarnation";
|
|
22
23
|
import { type CreateLifecycleAgentSessionResult, createLifecycleAgentSession } from "../sdk/lifecycle-session";
|
|
23
24
|
import { listManagedSessionCandidates, resolveManagedSessionScope } from "../sdk/session-directory";
|
|
@@ -505,6 +506,7 @@ export async function runSessionHost(
|
|
|
505
506
|
}
|
|
506
507
|
process.once("SIGTERM", stop);
|
|
507
508
|
process.once("SIGINT", stop);
|
|
509
|
+
startSessionHostGuard({ markerPath, pid: process.pid, effectMarker, incarnation, cwd, onLost: stop });
|
|
508
510
|
await new Promise<void>(() => {});
|
|
509
511
|
}
|
|
510
512
|
|
|
@@ -559,6 +561,7 @@ export default class Sdk extends Command {
|
|
|
559
561
|
const policy = (await Settings.loadForScope({ cwd, agentDir })).get("session.directoryMigration");
|
|
560
562
|
return policy === "disabled" ? "disabled" : "copy-retain";
|
|
561
563
|
},
|
|
564
|
+
beforePublicationTick: () => exitIfSourceGone(),
|
|
562
565
|
});
|
|
563
566
|
await broker.start();
|
|
564
567
|
if (!broker.ownsDiscovery) return;
|
package/src/commands/setup.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { Args, Command, Flags } from "@sayknow-cli/utils/cli";
|
|
5
5
|
import { runSetupCommand, type SetupCommandArgs, type SetupComponent } from "../cli/setup-cli";
|
|
6
6
|
import { initTheme } from "../modes/theme/theme";
|
|
7
|
+
import { PROVIDER_PRESETS } from "../setup/provider-onboarding";
|
|
7
8
|
|
|
8
9
|
const COMPONENTS: SetupComponent[] = [
|
|
9
10
|
"claude",
|
|
@@ -52,7 +53,9 @@ export default class Setup extends Command {
|
|
|
52
53
|
"skc-command": Flags.string({ description: "Command used to start `skc mcp-serve coordinator`" }),
|
|
53
54
|
target: Flags.string({ description: "Hermes config file target for config-only install" }),
|
|
54
55
|
"profile-dir": Flags.string({ description: "Hermes profile directory for full setup install" }),
|
|
55
|
-
preset: Flags.string({
|
|
56
|
+
preset: Flags.string({
|
|
57
|
+
description: `Provider preset: ${PROVIDER_PRESETS.map(preset => preset.id).join(", ")}`,
|
|
58
|
+
}),
|
|
56
59
|
compat: Flags.string({ description: "Provider compatibility: openai or anthropic" }),
|
|
57
60
|
provider: Flags.string({ description: "Provider id to add to models.yml" }),
|
|
58
61
|
"base-url": Flags.string({ description: "Provider API base URL" }),
|
|
@@ -1223,8 +1223,39 @@ export const SETTINGS_SCHEMA = {
|
|
|
1223
1223
|
type: "number",
|
|
1224
1224
|
default: 3,
|
|
1225
1225
|
validate: (value: number) => Number.isInteger(value) && value > 0,
|
|
1226
|
+
ui: {
|
|
1227
|
+
tab: "model",
|
|
1228
|
+
label: "Fallback Attempts per Model",
|
|
1229
|
+
description:
|
|
1230
|
+
"Tries on each model in the fallback chain (including the first) before moving to the next one. Missing credentials skip a model immediately.",
|
|
1231
|
+
options: [
|
|
1232
|
+
{ value: "1", label: "1 try" },
|
|
1233
|
+
{ value: "2", label: "2 tries" },
|
|
1234
|
+
{ value: "3", label: "3 tries" },
|
|
1235
|
+
{ value: "5", label: "5 tries" },
|
|
1236
|
+
],
|
|
1237
|
+
},
|
|
1238
|
+
},
|
|
1239
|
+
|
|
1240
|
+
/**
|
|
1241
|
+
* When the default model is blocked, keep going on another logged-in provider
|
|
1242
|
+
* after the configured chain and `fallback.models` run out. The extra entries
|
|
1243
|
+
* are computed per session and never written into the configured chain.
|
|
1244
|
+
*/
|
|
1245
|
+
"fallback.auto": {
|
|
1246
|
+
type: "boolean",
|
|
1247
|
+
default: true,
|
|
1248
|
+
ui: {
|
|
1249
|
+
tab: "model",
|
|
1250
|
+
label: "Automatic Model Fallback",
|
|
1251
|
+
description:
|
|
1252
|
+
"When the default model is blocked (no login, quota, auth or server errors), continue on a model from another logged-in provider. /fallback shows the chain.",
|
|
1253
|
+
},
|
|
1226
1254
|
},
|
|
1227
1255
|
|
|
1256
|
+
/** Models to try, in order, after the default chain. Edited with `/fallback`. */
|
|
1257
|
+
"fallback.models": { type: "array", default: EMPTY_STRING_ARRAY },
|
|
1258
|
+
|
|
1228
1259
|
// Retries
|
|
1229
1260
|
"retry.enabled": { type: "boolean", default: true },
|
|
1230
1261
|
|
|
@@ -1443,6 +1474,16 @@ export const SETTINGS_SCHEMA = {
|
|
|
1443
1474
|
],
|
|
1444
1475
|
},
|
|
1445
1476
|
},
|
|
1477
|
+
"startup.welcomeMouse": {
|
|
1478
|
+
type: "boolean",
|
|
1479
|
+
default: true,
|
|
1480
|
+
ui: {
|
|
1481
|
+
tab: "interaction",
|
|
1482
|
+
label: "Clickable Launch Card",
|
|
1483
|
+
description:
|
|
1484
|
+
"Until the first prompt, capture the mouse so a recent session on the launch card opens with one click. Terminal text selection needs Shift held meanwhile. Off: open sessions with ↓ and Enter.",
|
|
1485
|
+
},
|
|
1486
|
+
},
|
|
1446
1487
|
"startup.skipLogoAnimation": {
|
|
1447
1488
|
type: "boolean",
|
|
1448
1489
|
default: false,
|
|
@@ -3107,6 +3148,22 @@ export const SETTINGS_SCHEMA = {
|
|
|
3107
3148
|
},
|
|
3108
3149
|
},
|
|
3109
3150
|
|
|
3151
|
+
/**
|
|
3152
|
+
* The `locate` tool: find code by describing what it does, judged by Jev. Offered only
|
|
3153
|
+
* when a TypeSafe key is stored. Sends folder paths, file names and declaration lines
|
|
3154
|
+
* (never bodies or comments) to TypeSafe.
|
|
3155
|
+
*/
|
|
3156
|
+
"locate.enabled": {
|
|
3157
|
+
type: "boolean",
|
|
3158
|
+
default: true,
|
|
3159
|
+
ui: {
|
|
3160
|
+
tab: "tools",
|
|
3161
|
+
label: "Locate (Jev code search)",
|
|
3162
|
+
description:
|
|
3163
|
+
"Offer the locate tool when a TypeSafe key is stored. It sends folder paths, file names and declaration lines (no function bodies or comments) to TypeSafe to judge relevance.",
|
|
3164
|
+
},
|
|
3165
|
+
},
|
|
3166
|
+
|
|
3110
3167
|
"tools.essentialOverride": {
|
|
3111
3168
|
type: "array",
|
|
3112
3169
|
default: [] as string[],
|
|
@@ -3492,6 +3549,31 @@ export const SETTINGS_SCHEMA = {
|
|
|
3492
3549
|
// Providers
|
|
3493
3550
|
// ────────────────────────────────────────────────────────────────────────
|
|
3494
3551
|
|
|
3552
|
+
// Multi-account order. `SKC_CREDENTIAL_RANKING_MODE` overrides it per machine.
|
|
3553
|
+
"auth.credentialRankingMode": {
|
|
3554
|
+
type: "enum",
|
|
3555
|
+
values: ["balanced", "earliest-reset"] as const,
|
|
3556
|
+
default: "balanced",
|
|
3557
|
+
ui: {
|
|
3558
|
+
tab: "providers",
|
|
3559
|
+
label: "Multi-Account Order",
|
|
3560
|
+
description:
|
|
3561
|
+
"Which logged-in account of a provider a new session uses. A blocked or exhausted account is always skipped for the next one.",
|
|
3562
|
+
options: [
|
|
3563
|
+
{
|
|
3564
|
+
value: "balanced",
|
|
3565
|
+
label: "Balanced",
|
|
3566
|
+
description: "Least-used account first; spreads load and keeps headroom on every account",
|
|
3567
|
+
},
|
|
3568
|
+
{
|
|
3569
|
+
value: "earliest-reset",
|
|
3570
|
+
label: "Earliest reset",
|
|
3571
|
+
description: "Account whose usage window resets soonest first, so quota is not lost at reset",
|
|
3572
|
+
},
|
|
3573
|
+
],
|
|
3574
|
+
},
|
|
3575
|
+
},
|
|
3576
|
+
|
|
3495
3577
|
// Secret handling
|
|
3496
3578
|
"secrets.enabled": {
|
|
3497
3579
|
type: "boolean",
|
|
@@ -119,7 +119,7 @@ export function createTypeSafeDecisionBackend(deps: TypeSafeBackendDeps): Decisi
|
|
|
119
119
|
name: "typesafe",
|
|
120
120
|
async decide(request: DecisionRequest): Promise<DecisionResult | null> {
|
|
121
121
|
validateQuestions(request.questions);
|
|
122
|
-
|
|
122
|
+
let apiKey = await deps.registry.getApiKeyForProvider(TYPESAFE_PROVIDER, deps.sessionId);
|
|
123
123
|
// No key means the user never added TypeSafe. That is not an error — the next
|
|
124
124
|
// backend (their logged-in model) handles it.
|
|
125
125
|
if (!apiKey) return null;
|
|
@@ -132,13 +132,26 @@ export function createTypeSafeDecisionBackend(deps: TypeSafeBackendDeps): Decisi
|
|
|
132
132
|
request.signal?.addEventListener("abort", abortOnCaller, { once: true });
|
|
133
133
|
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
134
134
|
const started = Date.now();
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
const send = (key: string) =>
|
|
136
|
+
doFetch(`${baseUrl}/v1/systemone`, {
|
|
137
137
|
method: "POST",
|
|
138
|
-
headers: { Authorization: `Bearer ${
|
|
138
|
+
headers: { Authorization: `Bearer ${key}`, "Content-Type": "application/json" },
|
|
139
139
|
body: JSON.stringify({ state: request.state, model, questions: toWireQuestions(request.questions) }),
|
|
140
140
|
signal: controller.signal,
|
|
141
141
|
});
|
|
142
|
+
try {
|
|
143
|
+
let response = await send(apiKey);
|
|
144
|
+
if (response.status === 401 || response.status === 403) {
|
|
145
|
+
// A session reads the credential store once, at startup. A key replaced from
|
|
146
|
+
// another session (or `skc setup typesafe`) stays invisible here, so every
|
|
147
|
+
// request kept sending the revoked key. Reload once; retry only if it changed.
|
|
148
|
+
const refreshed = await reloadedKey(deps, apiKey);
|
|
149
|
+
if (refreshed && !controller.signal.aborted) {
|
|
150
|
+
await response.body?.cancel().catch(() => {});
|
|
151
|
+
apiKey = refreshed;
|
|
152
|
+
response = await send(apiKey);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
142
155
|
if (!response.ok) {
|
|
143
156
|
logger.debug("decisions/typesafe: request failed", {
|
|
144
157
|
status: response.status,
|
|
@@ -169,3 +182,24 @@ export function createTypeSafeDecisionBackend(deps: TypeSafeBackendDeps): Decisi
|
|
|
169
182
|
},
|
|
170
183
|
};
|
|
171
184
|
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Re-read stored credentials and return the TypeSafe key if it differs from the one
|
|
188
|
+
* that was just rejected. Undefined when nothing changed (the key really is bad) or the
|
|
189
|
+
* store cannot be reloaded, so a genuinely revoked key costs one extra read, not a retry.
|
|
190
|
+
*/
|
|
191
|
+
async function reloadedKey(deps: TypeSafeBackendDeps, rejected: string): Promise<string | undefined> {
|
|
192
|
+
const storage = (deps.registry as { authStorage?: { reload?: () => Promise<void> } }).authStorage;
|
|
193
|
+
if (typeof storage?.reload !== "function") return undefined;
|
|
194
|
+
try {
|
|
195
|
+
await storage.reload();
|
|
196
|
+
const current = await deps.registry.getApiKeyForProvider(TYPESAFE_PROVIDER, deps.sessionId);
|
|
197
|
+
if (current && current !== rejected) {
|
|
198
|
+
logger.debug("decisions/typesafe: picked up a key replaced since this session started");
|
|
199
|
+
return current;
|
|
200
|
+
}
|
|
201
|
+
} catch (error) {
|
|
202
|
+
logger.debug("decisions/typesafe: credential reload failed", { error: String(error) });
|
|
203
|
+
}
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
@@ -235,6 +235,31 @@ export const deSettings: Record<string, string> = {
|
|
|
235
235
|
"set:task.serviceTier:o:claude-only:l": "Priorität (nur Claude)",
|
|
236
236
|
"set:task.serviceTier:o:claude-only:d":
|
|
237
237
|
"Anthropic-Schnellmodus bei direkten Claude-Anfragen; sonst ignoriert (inkl. Bedrock/Vertex)",
|
|
238
|
+
"set:fallback.maxAttempts:l": "Fallback-Versuche pro Modell",
|
|
239
|
+
"set:fallback.maxAttempts:d":
|
|
240
|
+
"Versuche je Modell der Fallback-Kette (einschließlich des ersten), bevor das nächste drankommt. Modelle ohne Anmeldedaten werden sofort übersprungen.",
|
|
241
|
+
"set:fallback.maxAttempts:o:1:l": "1 Versuch",
|
|
242
|
+
"set:fallback.maxAttempts:o:2:l": "2 Versuche",
|
|
243
|
+
"set:fallback.maxAttempts:o:3:l": "3 Versuche",
|
|
244
|
+
"set:fallback.maxAttempts:o:5:l": "5 Versuche",
|
|
245
|
+
"set:fallback.auto:l": "Automatischer Modell-Fallback",
|
|
246
|
+
"set:fallback.auto:d":
|
|
247
|
+
"Ist das Standardmodell blockiert (keine Anmeldung, Kontingent, Auth- oder Serverfehler), mit einem Modell eines anderen angemeldeten Anbieters weitermachen. /fallback zeigt die Kette.",
|
|
248
|
+
"set:auth.credentialRankingMode:l": "Reihenfolge mehrerer Konten",
|
|
249
|
+
"set:auth.credentialRankingMode:d":
|
|
250
|
+
"Welches angemeldete Konto eines Anbieters eine neue Sitzung verwendet. Ein blockiertes oder erschöpftes Konto übergibt immer an das nächste.",
|
|
251
|
+
"set:auth.credentialRankingMode:o:balanced:l": "Ausgewogen",
|
|
252
|
+
"set:auth.credentialRankingMode:o:balanced:d":
|
|
253
|
+
"Am wenigsten genutztes Konto zuerst; verteilt die Last und lässt jedem Konto Reserve",
|
|
254
|
+
"set:auth.credentialRankingMode:o:earliest-reset:l": "Früheste Zurücksetzung",
|
|
255
|
+
"set:auth.credentialRankingMode:o:earliest-reset:d":
|
|
256
|
+
"Konto, dessen Nutzungsfenster zuerst zurückgesetzt wird, zuerst, damit kein Kontingent verfällt",
|
|
257
|
+
"set:locate.enabled:l": "Locate (Jev-Codesuche)",
|
|
258
|
+
"set:locate.enabled:d":
|
|
259
|
+
"Bietet das locate-Werkzeug an, wenn ein TypeSafe-Schlüssel gespeichert ist. Zur Relevanzbewertung werden Ordnerpfade, Dateinamen und Deklarationszeilen (ohne Funktionsrümpfe und Kommentare) an TypeSafe gesendet.",
|
|
260
|
+
"set:startup.welcomeMouse:l": "Klickbare Startkarte",
|
|
261
|
+
"set:startup.welcomeMouse:d":
|
|
262
|
+
"Bis zum ersten Prompt die Maus übernehmen, damit eine letzte Sitzung auf der Startkarte mit einem Klick öffnet. Terminaltext währenddessen mit gedrückter Umschalttaste markieren. Aus: mit ↓ und Enter öffnen.",
|
|
238
263
|
"set:retry.maxRetries:l": "Wiederholungsversuche",
|
|
239
264
|
"set:retry.maxRetries:d": "Maximale Wiederholungsversuche bei API-Fehlern",
|
|
240
265
|
"set:retry.maxRetries:o:1:l": "1 Wiederholung",
|
|
@@ -773,6 +798,7 @@ export const deSettings: Record<string, string> = {
|
|
|
773
798
|
"set:searxng.endpoint:l": "SearXNG-Endpunkt",
|
|
774
799
|
"set:searxng.endpoint:d": "Basis-URL für selbst gehostete Suche",
|
|
775
800
|
"cmd:model:d": "Modell auswählen (öffnet Auswahloberfläche)",
|
|
801
|
+
"cmd:fallback:d": "Modelle anzeigen oder bearbeiten, die bei blockiertem Standardmodell versucht werden",
|
|
776
802
|
"cmd:fast:d": "Prioritäts-Service-Tier umschalten (OpenAI service_tier=priority, Anthropic speed=fast)",
|
|
777
803
|
"cmd:export:d": "Sitzung in HTML-Datei exportieren",
|
|
778
804
|
"cmd:dump:d": "Sitzungstranskript in die Zwischenablage kopieren",
|
package/src/i18n/messages/de.ts
CHANGED
|
@@ -15,6 +15,8 @@ export const de: Partial<Record<MsgKey, string>> = {
|
|
|
15
15
|
"welcome.noSessions": "Keine gespeicherten Verläufe",
|
|
16
16
|
"welcome.allSessions": "{key} alle Sitzungen",
|
|
17
17
|
"welcome.continue": "{key} fortsetzen",
|
|
18
|
+
"welcome.pick": "{key} wählen",
|
|
19
|
+
"welcome.pickActive": "↑↓ bewegen · ⏎ öffnen · esc zurück",
|
|
18
20
|
"welcome.sessions": "Sitzungen",
|
|
19
21
|
"welcome.chooseModel": "Modell auswählen",
|
|
20
22
|
"welcome.modelHint": "ctrl+l zum Auswählen · / für Befehle",
|
package/src/i18n/messages/en.ts
CHANGED
|
@@ -20,6 +20,8 @@ export const en = {
|
|
|
20
20
|
"welcome.noSessions": "No saved sessions",
|
|
21
21
|
"welcome.allSessions": "{key} all sessions",
|
|
22
22
|
"welcome.continue": "{key} continue",
|
|
23
|
+
"welcome.pick": "{key} pick",
|
|
24
|
+
"welcome.pickActive": "↑↓ move · ⏎ open · esc back",
|
|
23
25
|
"welcome.sessions": "sessions",
|
|
24
26
|
"welcome.chooseModel": "choose a model",
|
|
25
27
|
"welcome.modelHint": "ctrl+l to pick · / for commands",
|
|
@@ -216,6 +216,31 @@ export const esSettings: Record<string, string> = {
|
|
|
216
216
|
"set:task.serviceTier:o:claude-only:l": "Prioridad (solo Claude)",
|
|
217
217
|
"set:task.serviceTier:o:claude-only:d":
|
|
218
218
|
"Modo rápido de Anthropic en solicitudes directas de Claude; se ignora en el resto (incl. Bedrock/Vertex)",
|
|
219
|
+
"set:fallback.maxAttempts:l": "Intentos de reserva por modelo",
|
|
220
|
+
"set:fallback.maxAttempts:d":
|
|
221
|
+
"Intentos por cada modelo de la cadena de reserva (incluido el primero) antes de pasar al siguiente. Los modelos sin credenciales se omiten de inmediato.",
|
|
222
|
+
"set:fallback.maxAttempts:o:1:l": "1 intento",
|
|
223
|
+
"set:fallback.maxAttempts:o:2:l": "2 intentos",
|
|
224
|
+
"set:fallback.maxAttempts:o:3:l": "3 intentos",
|
|
225
|
+
"set:fallback.maxAttempts:o:5:l": "5 intentos",
|
|
226
|
+
"set:fallback.auto:l": "Reserva automática de modelo",
|
|
227
|
+
"set:fallback.auto:d":
|
|
228
|
+
"Si el modelo predeterminado está bloqueado (sin sesión, cuota, errores de autenticación o servidor), continúa con un modelo de otro proveedor con sesión iniciada. /fallback muestra la cadena.",
|
|
229
|
+
"set:auth.credentialRankingMode:l": "Orden de varias cuentas",
|
|
230
|
+
"set:auth.credentialRankingMode:d":
|
|
231
|
+
"Qué cuenta con sesión iniciada de un proveedor usa una sesión nueva. Una cuenta bloqueada o agotada siempre cede el paso a la siguiente.",
|
|
232
|
+
"set:auth.credentialRankingMode:o:balanced:l": "Equilibrado",
|
|
233
|
+
"set:auth.credentialRankingMode:o:balanced:d":
|
|
234
|
+
"Primero la cuenta menos usada; reparte la carga y deja margen en cada cuenta",
|
|
235
|
+
"set:auth.credentialRankingMode:o:earliest-reset:l": "Reinicio más próximo",
|
|
236
|
+
"set:auth.credentialRankingMode:o:earliest-reset:d":
|
|
237
|
+
"Primero la cuenta cuya ventana de uso se reinicia antes, para no perder cuota al reiniciarse",
|
|
238
|
+
"set:locate.enabled:l": "Locate (búsqueda de código con Jev)",
|
|
239
|
+
"set:locate.enabled:d":
|
|
240
|
+
"Ofrece la herramienta locate cuando hay una clave de TypeSafe guardada. Para juzgar la relevancia envía a TypeSafe rutas de carpetas, nombres de archivo y líneas de declaración (sin cuerpos de función ni comentarios).",
|
|
241
|
+
"set:startup.welcomeMouse:l": "Tarjeta de inicio clicable",
|
|
242
|
+
"set:startup.welcomeMouse:d":
|
|
243
|
+
"Hasta el primer prompt, captura el ratón para abrir una sesión reciente de la tarjeta de inicio con un clic. Mientras tanto, selecciona texto del terminal con Mayús pulsada. Desactivado: abre con ↓ y Enter.",
|
|
219
244
|
"set:retry.maxRetries:l": "Intentos de reintento",
|
|
220
245
|
"set:retry.maxRetries:d": "Número máximo de reintentos ante errores de la API",
|
|
221
246
|
"set:retry.maxRetries:o:1:l": "1 reintento",
|
|
@@ -766,6 +791,7 @@ export const esSettings: Record<string, string> = {
|
|
|
766
791
|
"set:searxng.endpoint:l": "Endpoint de SearXNG",
|
|
767
792
|
"set:searxng.endpoint:d": "URL base de búsqueda autohospedada",
|
|
768
793
|
"cmd:model:d": "Seleccionar modelo (abre la interfaz de selección)",
|
|
794
|
+
"cmd:fallback:d": "Ver o editar los modelos que se prueban cuando el modelo predeterminado está bloqueado",
|
|
769
795
|
"cmd:fast:d": "Alternar el nivel de servicio prioritario (OpenAI service_tier=priority, Anthropic speed=fast)",
|
|
770
796
|
"cmd:export:d": "Exportar sesión a archivo HTML",
|
|
771
797
|
"cmd:dump:d": "Copiar la transcripción de la sesión al portapapeles",
|
package/src/i18n/messages/es.ts
CHANGED
|
@@ -15,6 +15,8 @@ export const es: Partial<Record<MsgKey, string>> = {
|
|
|
15
15
|
"welcome.noSessions": "Sin historiales guardados",
|
|
16
16
|
"welcome.allSessions": "{key} todas las sesiones",
|
|
17
17
|
"welcome.continue": "{key} continuar",
|
|
18
|
+
"welcome.pick": "{key} elegir",
|
|
19
|
+
"welcome.pickActive": "↑↓ mover · ⏎ abrir · esc volver",
|
|
18
20
|
"welcome.sessions": "sesiones",
|
|
19
21
|
"welcome.chooseModel": "elige un modelo",
|
|
20
22
|
"welcome.modelHint": "ctrl+l para elegir · / para comandos",
|
|
@@ -216,6 +216,31 @@ export const frSettings: Record<string, string> = {
|
|
|
216
216
|
"set:task.serviceTier:o:claude-only:l": "Priorité (Claude uniquement)",
|
|
217
217
|
"set:task.serviceTier:o:claude-only:d":
|
|
218
218
|
"Mode rapide d'Anthropic sur les requêtes Claude directes ; ignoré ailleurs (y compris Bedrock/Vertex)",
|
|
219
|
+
"set:fallback.maxAttempts:l": "Tentatives de repli par modèle",
|
|
220
|
+
"set:fallback.maxAttempts:d":
|
|
221
|
+
"Nombre d'essais de chaque modèle de la chaîne de repli (y compris le premier) avant de passer au suivant. Un modèle sans identifiants est ignoré aussitôt.",
|
|
222
|
+
"set:fallback.maxAttempts:o:1:l": "1 essai",
|
|
223
|
+
"set:fallback.maxAttempts:o:2:l": "2 essais",
|
|
224
|
+
"set:fallback.maxAttempts:o:3:l": "3 essais",
|
|
225
|
+
"set:fallback.maxAttempts:o:5:l": "5 essais",
|
|
226
|
+
"set:fallback.auto:l": "Repli automatique de modèle",
|
|
227
|
+
"set:fallback.auto:d":
|
|
228
|
+
"Si le modèle par défaut est bloqué (pas de connexion, quota, erreurs d'authentification ou serveur), continuer avec un modèle d'un autre fournisseur connecté. /fallback affiche la chaîne.",
|
|
229
|
+
"set:auth.credentialRankingMode:l": "Ordre des comptes multiples",
|
|
230
|
+
"set:auth.credentialRankingMode:d":
|
|
231
|
+
"Quel compte connecté d'un fournisseur une nouvelle session utilise. Un compte bloqué ou épuisé passe toujours la main au suivant.",
|
|
232
|
+
"set:auth.credentialRankingMode:o:balanced:l": "Équilibré",
|
|
233
|
+
"set:auth.credentialRankingMode:o:balanced:d":
|
|
234
|
+
"Le compte le moins utilisé d'abord ; répartit la charge et garde de la marge sur chaque compte",
|
|
235
|
+
"set:auth.credentialRankingMode:o:earliest-reset:l": "Réinitialisation la plus proche",
|
|
236
|
+
"set:auth.credentialRankingMode:o:earliest-reset:d":
|
|
237
|
+
"Le compte dont la fenêtre d'utilisation se réinitialise le plus tôt d'abord, pour ne pas perdre de quota",
|
|
238
|
+
"set:locate.enabled:l": "Locate (recherche de code Jev)",
|
|
239
|
+
"set:locate.enabled:d":
|
|
240
|
+
"Propose l'outil locate quand une clé TypeSafe est enregistrée. Pour juger la pertinence, il envoie à TypeSafe les chemins de dossiers, les noms de fichiers et les lignes de déclaration (sans corps de fonctions ni commentaires).",
|
|
241
|
+
"set:startup.welcomeMouse:l": "Carte de démarrage cliquable",
|
|
242
|
+
"set:startup.welcomeMouse:d":
|
|
243
|
+
"Jusqu'au premier prompt, capturer la souris pour ouvrir une session récente de la carte de démarrage d'un clic. Sélectionnez le texte du terminal avec Maj enfoncée en attendant. Désactivé : ouvrir avec ↓ et Entrée.",
|
|
219
244
|
"set:retry.maxRetries:l": "Tentatives de nouvel essai",
|
|
220
245
|
"set:retry.maxRetries:d": "Nombre maximal de nouvelles tentatives en cas d'erreurs API",
|
|
221
246
|
"set:retry.maxRetries:o:1:l": "1 nouvel essai",
|
|
@@ -738,6 +763,7 @@ export const frSettings: Record<string, string> = {
|
|
|
738
763
|
"set:searxng.endpoint:l": "Point de terminaison SearXNG",
|
|
739
764
|
"set:searxng.endpoint:d": "URL de base de recherche auto-hébergée",
|
|
740
765
|
"cmd:model:d": "Sélectionner le modèle (ouvre l'interface de sélection)",
|
|
766
|
+
"cmd:fallback:d": "Afficher ou modifier les modèles essayés quand le modèle par défaut est bloqué",
|
|
741
767
|
"cmd:fast:d":
|
|
742
768
|
"Activer/désactiver le niveau de service prioritaire (OpenAI service_tier=priority, Anthropic speed=fast)",
|
|
743
769
|
"cmd:export:d": "Exporter la session vers un fichier HTML",
|
package/src/i18n/messages/fr.ts
CHANGED
|
@@ -15,6 +15,8 @@ export const fr: Partial<Record<MsgKey, string>> = {
|
|
|
15
15
|
"welcome.noSessions": "Aucun historique enregistré",
|
|
16
16
|
"welcome.allSessions": "{key} toutes les sessions",
|
|
17
17
|
"welcome.continue": "{key} reprendre",
|
|
18
|
+
"welcome.pick": "{key} choisir",
|
|
19
|
+
"welcome.pickActive": "↑↓ déplacer · ⏎ ouvrir · esc retour",
|
|
18
20
|
"welcome.sessions": "sessions",
|
|
19
21
|
"welcome.chooseModel": "choisir un modèle",
|
|
20
22
|
"welcome.modelHint": "ctrl+l pour choisir · / pour les commandes",
|
|
@@ -247,6 +247,31 @@ export const jaSettings: Record<string, string> = {
|
|
|
247
247
|
"set:task.serviceTier:o:claude-only:l": "優先度 (Claude のみ)",
|
|
248
248
|
"set:task.serviceTier:o:claude-only:d":
|
|
249
249
|
"直接の Claude リクエストに Anthropic 高速モードを適用。それ以外では無視されます (Bedrock/Vertex を含む)",
|
|
250
|
+
"set:fallback.maxAttempts:l": "モデルごとのフォールバック試行回数",
|
|
251
|
+
"set:fallback.maxAttempts:d":
|
|
252
|
+
"フォールバックチェーンの各モデル (最初のモデルを含む) を何回試してから次へ進むか。認証情報のないモデルはすぐにスキップします。",
|
|
253
|
+
"set:fallback.maxAttempts:o:1:l": "1 回",
|
|
254
|
+
"set:fallback.maxAttempts:o:2:l": "2 回",
|
|
255
|
+
"set:fallback.maxAttempts:o:3:l": "3 回",
|
|
256
|
+
"set:fallback.maxAttempts:o:5:l": "5 回",
|
|
257
|
+
"set:fallback.auto:l": "自動モデルフォールバック",
|
|
258
|
+
"set:fallback.auto:d":
|
|
259
|
+
"既定モデルが使えないとき (未ログイン、上限、認証・サーバーエラー)、ログイン済みの別プロバイダーのモデルで続行します。/fallback でチェーンを確認できます。",
|
|
260
|
+
"set:auth.credentialRankingMode:l": "複数アカウントの順序",
|
|
261
|
+
"set:auth.credentialRankingMode:d":
|
|
262
|
+
"プロバイダーにログイン済みのアカウントのうち、新しいセッションがどれを使うか。ブロック・上限到達のアカウントは常に次へ回ります。",
|
|
263
|
+
"set:auth.credentialRankingMode:o:balanced:l": "バランス",
|
|
264
|
+
"set:auth.credentialRankingMode:o:balanced:d":
|
|
265
|
+
"使用量が最も少ないアカウントから。負荷を分散し、すべてのアカウントに余裕を残します",
|
|
266
|
+
"set:auth.credentialRankingMode:o:earliest-reset:l": "リセットが早い順",
|
|
267
|
+
"set:auth.credentialRankingMode:o:earliest-reset:d":
|
|
268
|
+
"使用量ウィンドウが最も早くリセットされるアカウントから。リセットで失われる枠を先に使います",
|
|
269
|
+
"set:locate.enabled:l": "Locate (Jev コード検索)",
|
|
270
|
+
"set:locate.enabled:d":
|
|
271
|
+
"TypeSafe キーがあるとき locate ツールを提供します。関連性の判定のため、フォルダパス、ファイル名、宣言行 (関数本体・コメントは除く) を TypeSafe に送ります。",
|
|
272
|
+
"set:startup.welcomeMouse:l": "クリックできる起動カード",
|
|
273
|
+
"set:startup.welcomeMouse:d":
|
|
274
|
+
"最初のプロンプトまでマウスを受け取り、起動カードの最近のセッションをワンクリックで開きます。その間の端末テキスト選択は Shift を押しながら行います。オフでは ↓ と Enter で開きます。",
|
|
250
275
|
"set:retry.maxRetries:l": "リトライ回数",
|
|
251
276
|
"set:retry.maxRetries:d": "API エラー時の最大リトライ回数",
|
|
252
277
|
"set:retry.maxRetries:o:1:l": "1 回リトライ",
|
|
@@ -779,6 +804,7 @@ export const jaSettings: Record<string, string> = {
|
|
|
779
804
|
"cmd:theme:d": "テーマセレクターを開く",
|
|
780
805
|
"cmd:goal:d": "ゴールモードを切り替え(このセッションの永続的な自律目標)",
|
|
781
806
|
"cmd:model:d": "モデルを選択(セレクター UI を開く)",
|
|
807
|
+
"cmd:fallback:d": "既定モデルが使えないときに試すモデルを表示・編集",
|
|
782
808
|
"cmd:fast:d": "優先サービスティアを切り替え(OpenAI service_tier=priority、Anthropic speed=fast)",
|
|
783
809
|
"cmd:export:d": "セッションを HTML ファイルにエクスポート",
|
|
784
810
|
"cmd:dump:d": "セッションのトランスクリプトをクリップボードにコピー",
|
package/src/i18n/messages/ja.ts
CHANGED
|
@@ -12,6 +12,8 @@ export const ja: Partial<Record<MsgKey, string>> = {
|
|
|
12
12
|
"welcome.noSessions": "保存されたセッションなし",
|
|
13
13
|
"welcome.allSessions": "{key} すべて表示",
|
|
14
14
|
"welcome.continue": "{key} 続ける",
|
|
15
|
+
"welcome.pick": "{key} 選択",
|
|
16
|
+
"welcome.pickActive": "↑↓ 移動 · ⏎ 開く · esc 戻る",
|
|
15
17
|
"welcome.sessions": "セッション",
|
|
16
18
|
"welcome.chooseModel": "モデルを選択",
|
|
17
19
|
"welcome.modelHint": "ctrl+l で選択 · / でコマンド",
|
|
@@ -248,6 +248,30 @@ export const koSettings: Record<string, string> = {
|
|
|
248
248
|
"set:task.serviceTier:o:claude-only:l": "우선순위 (Claude 전용)",
|
|
249
249
|
"set:task.serviceTier:o:claude-only:d":
|
|
250
250
|
"직접 Claude 요청에 Anthropic 고속 모드 적용. 그 외에는 무시됨 (Bedrock/Vertex 포함)",
|
|
251
|
+
"set:fallback.maxAttempts:l": "모델별 폴백 시도 횟수",
|
|
252
|
+
"set:fallback.maxAttempts:d":
|
|
253
|
+
"폴백 체인의 각 모델(첫 모델 포함)을 몇 번 시도한 뒤 다음 모델로 넘어갈지. 자격 증명이 없는 모델은 바로 건너뜁니다.",
|
|
254
|
+
"set:fallback.maxAttempts:o:1:l": "1회",
|
|
255
|
+
"set:fallback.maxAttempts:o:2:l": "2회",
|
|
256
|
+
"set:fallback.maxAttempts:o:3:l": "3회",
|
|
257
|
+
"set:fallback.maxAttempts:o:5:l": "5회",
|
|
258
|
+
"set:fallback.auto:l": "자동 모델 폴백",
|
|
259
|
+
"set:fallback.auto:d":
|
|
260
|
+
"기본 모델이 막히면(로그인 없음, 한도, 인증·서버 오류) 로그인된 다른 공급자의 모델로 이어서 진행합니다. /fallback 에서 체인을 볼 수 있습니다.",
|
|
261
|
+
"set:auth.credentialRankingMode:l": "다중 계정 순서",
|
|
262
|
+
"set:auth.credentialRankingMode:d":
|
|
263
|
+
"한 공급자에 로그인된 계정 중 새 세션이 어떤 계정을 쓸지. 막히거나 한도가 찬 계정은 항상 다음 계정으로 넘어갑니다.",
|
|
264
|
+
"set:auth.credentialRankingMode:o:balanced:l": "균형",
|
|
265
|
+
"set:auth.credentialRankingMode:o:balanced:d": "가장 덜 쓴 계정부터. 부하를 나누고 모든 계정에 여유를 남깁니다",
|
|
266
|
+
"set:auth.credentialRankingMode:o:earliest-reset:l": "빨리 초기화되는 순",
|
|
267
|
+
"set:auth.credentialRankingMode:o:earliest-reset:d":
|
|
268
|
+
"사용량 구간이 가장 먼저 초기화되는 계정부터. 초기화 때 사라질 한도를 먼저 씁니다",
|
|
269
|
+
"set:locate.enabled:l": "Locate (Jev 코드 검색)",
|
|
270
|
+
"set:locate.enabled:d":
|
|
271
|
+
"TypeSafe 키가 있으면 locate 도구를 제공합니다. 관련성 판단을 위해 폴더 경로, 파일 이름, 선언 줄(함수 본문·주석 제외)을 TypeSafe로 보냅니다.",
|
|
272
|
+
"set:startup.welcomeMouse:l": "클릭 가능한 시작 카드",
|
|
273
|
+
"set:startup.welcomeMouse:d":
|
|
274
|
+
"첫 프롬프트 전까지 마우스를 받아 시작 카드의 최근 세션을 한 번 클릭으로 엽니다. 그동안 터미널 텍스트 선택은 Shift를 누른 채로 하세요. 끄면 ↓와 Enter로 엽니다.",
|
|
251
275
|
"set:retry.maxRetries:l": "재시도 횟수",
|
|
252
276
|
"set:retry.maxRetries:d": "API 오류 시 최대 재시도 횟수",
|
|
253
277
|
"set:retry.maxRetries:o:1:l": "1회 재시도",
|
|
@@ -768,6 +792,7 @@ export const koSettings: Record<string, string> = {
|
|
|
768
792
|
"cmd:theme:d": "테마 선택기 열기",
|
|
769
793
|
"cmd:goal:d": "목표 모드 토글 (이 세션의 지속적 자율 목표)",
|
|
770
794
|
"cmd:model:d": "모델 선택 (선택기 UI 열기)",
|
|
795
|
+
"cmd:fallback:d": "기본 모델이 막혔을 때 시도할 모델 보기·편집",
|
|
771
796
|
"cmd:fast:d": "우선순위 서비스 티어 토글 (OpenAI service_tier=priority, Anthropic speed=fast)",
|
|
772
797
|
"cmd:export:d": "세션을 HTML 파일로 내보내기",
|
|
773
798
|
"cmd:dump:d": "세션 기록을 클립보드에 복사",
|
package/src/i18n/messages/ko.ts
CHANGED
|
@@ -12,6 +12,8 @@ export const ko: Partial<Record<MsgKey, string>> = {
|
|
|
12
12
|
"welcome.noSessions": "저장된 세션 없음",
|
|
13
13
|
"welcome.allSessions": "{key} 전체 보기",
|
|
14
14
|
"welcome.continue": "{key} 이어하기",
|
|
15
|
+
"welcome.pick": "{key} 선택",
|
|
16
|
+
"welcome.pickActive": "↑↓ 이동 · ⏎ 열기 · esc 닫기",
|
|
15
17
|
"welcome.sessions": "세션",
|
|
16
18
|
"welcome.chooseModel": "모델 선택",
|
|
17
19
|
"welcome.modelHint": "ctrl+l 선택 · / 명령",
|