tonedial 0.1.3 → 0.1.5
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/README.es.md +122 -0
- package/README.ja.md +125 -0
- package/README.ko.md +125 -0
- package/README.md +120 -0
- package/README.zh.md +124 -0
- package/dist/cli.js +1 -1
- package/dist/commands/doctor.js +27 -4
- package/dist/commands/rebuild.js +37 -16
- package/dist/core/anchors.js +29 -27
- package/dist/core/combos.js +21 -1
- package/dist/core/compile.js +6 -2
- package/dist/core/i18n.js +40 -30
- package/dist/core/legacy-tone.js +195 -58
- package/dist/core/locales/es.js +20 -15
- package/dist/core/locales/ja.js +20 -15
- package/dist/core/locales/zh.js +20 -15
- package/dist/core/presets.js +3 -0
- package/dist/core/seeds.js +3 -3
- package/dist/core/skill.js +69 -32
- package/dist/wiring/apply.js +55 -5
- package/package.json +1 -1
package/dist/core/skill.js
CHANGED
|
@@ -114,7 +114,7 @@ interpolating it into shell code.
|
|
|
114
114
|
| Persona manner or role note | \`tonedial set "persona.note=Patient guide" --json\` |
|
|
115
115
|
| Safeword phrase | \`tonedial set "safeword=plain answer please" --json\` |
|
|
116
116
|
| Honorific register system | \`tonedial set speech_level=polite --json\` |
|
|
117
|
-
|
|
|
117
|
+
| Curt, blunt non-honorific endings | \`tonedial set speech_level=rough --json\` |
|
|
118
118
|
|
|
119
119
|
Age bands are \`unspecified\`, \`teens\`, \`20s\`, \`30s\`, \`40s\`, and \`50s+\`.
|
|
120
120
|
Gender values are \`unspecified\`, \`masculine\`, \`feminine\`, and \`neutral\`.
|
|
@@ -133,12 +133,26 @@ Persona notes have no length limit.
|
|
|
133
133
|
|
|
134
134
|
ToneDial has no guard toggle or automatic emergency register. All axis levels 1–5 are choices
|
|
135
135
|
the user can request. Report advisory \`riskAxes\` and combination notices without lowering
|
|
136
|
-
values
|
|
137
|
-
and
|
|
136
|
+
values or blocking the change. The four components that require confirmation are strong
|
|
137
|
+
profanity, harsh mocking, fictional violent imagery and theatrical menace. Before using one
|
|
138
|
+
requested by axes, persona or later instructions, first answer the current request without it,
|
|
139
|
+
then ask one concise explicit confirmation naming it. Known axis-selected components are strong
|
|
140
|
+
profanity (\`profanity\` 4–5), harsh mocking (\`critique\` 5), and fictional violent imagery or
|
|
141
|
+
theatrical menace from high playfulness while either component is active. Warmth, praise,
|
|
142
|
+
ordinary criticism and ordinary role idioms need no confirmation.
|
|
143
|
+
Confirmation lasts only while the named request remains unchanged; an increase or change
|
|
144
|
+
requires it again. Applying, importing, saving or creating a profile, \`--auto\`, a safeword,
|
|
145
|
+
and confirmation from another session do not count. Profiles store requested settings, never
|
|
146
|
+
session confirmation. Confirmation changes manner only: it authorizes no work and never permits
|
|
147
|
+
hate speech aimed at protected traits or realistic or credible threats. Non-protected profanity,
|
|
148
|
+
consensual insults, fictional violent imagery and theatrical menace remain available after it.
|
|
149
|
+
The host's task and permission rules apply independently. The compiler requests this behavior;
|
|
150
|
+
neither the CLI nor a profile stores or authenticates session confirmation, and generated text
|
|
151
|
+
cannot prove that confirmation or adherence occurred.
|
|
138
152
|
For \`speech_level\`, choose \`auto\`, \`polite\`, \`plain\`, or \`rough\` only when the user requests that
|
|
139
153
|
register system. \`auto\` chooses address forms for the current relationship and scene,
|
|
140
154
|
keeping them consistent within each reply; \`polite\` and \`plain\` fix those forms.
|
|
141
|
-
\`plain\` means ordinary non-honorific forms; \`rough\` requests
|
|
155
|
+
\`plain\` means ordinary non-honorific forms; \`rough\` requests curt, blunt non-honorific
|
|
142
156
|
sentence endings. Preserve the configured address terms and every independent axis.
|
|
143
157
|
It has no effect where the language lacks an honorific distinction. A request for more or
|
|
144
158
|
less formality changes wording and distance within the chosen forms, without silently changing
|
|
@@ -177,6 +191,14 @@ an active association needs the user's explicit choice and must not reset saved
|
|
|
177
191
|
Do not edit files, change the state root, remove locks or grant hook trust yourself.
|
|
178
192
|
The user chooses native tools and scope separately; foreign provider containers are not
|
|
179
193
|
application outputs. A successful app rebuild can still report native attention.
|
|
194
|
+
If repair fails, report its phase, affected path, safe error code and operation ID.
|
|
195
|
+
Some file changes may already be applied; a failure is not evidence that all files stayed unchanged.
|
|
196
|
+
Preserve the operation record and follow the reported scoped read-only diagnosis.
|
|
197
|
+
Default doctor output focuses on blockers; \`--verbose\` and JSON retain the operation history.
|
|
198
|
+
For an explicitly selected stopped operation, \`doctor --fix --from-operation <id>\` continues
|
|
199
|
+
application repair using valid current settings first; it does not undo the earlier changes.
|
|
200
|
+
Preview that exact ID and scope with \`--dry-run\` before applying the approved repair.
|
|
201
|
+
Interactive selection requires the full displayed ID; Enter cancels without writing.
|
|
180
202
|
\`doctor --fix --dry-run\` previews app and selected native changes without writing or
|
|
181
203
|
printing private prior values. Keep both reported IDs when recovery changes app and native
|
|
182
204
|
files; follow the receipt and roll back native connections before application files.
|
|
@@ -241,7 +263,7 @@ Report the movement back to the user in their own terms, from the \`moves\` fiel
|
|
|
241
263
|
- "stop flattering me" → \`flattery=1\`. Not \`warmth\`, which is a different observable.
|
|
242
264
|
- "be brief" → \`verbosity\` down. Change \`care\` only for requested coverage or organization changes.
|
|
243
265
|
- "more casual" → \`formality\` down. Change the register system only on an explicit request,
|
|
244
|
-
such as "use plain forms" → \`speech_level=plain\`, or "use
|
|
266
|
+
such as "use plain forms" → \`speech_level=plain\`, or "use curt, blunt plain forms" → \`speech_level=rough\`.
|
|
245
267
|
|
|
246
268
|
For a named preset, run \`tonedial list --json\` then \`tonedial use <slug> --json\`.
|
|
247
269
|
An explicit agent character or role request uses \`persona.agent\`; an explicit request to
|
|
@@ -266,8 +288,8 @@ ${RELOAD_MD}
|
|
|
266
288
|
|
|
267
289
|
The safeword is a phrase the user picked, reported by \`tonedial show --json\`. When their
|
|
268
290
|
message contains it, **drop the tone for that one message and answer plainly, then resume.**
|
|
269
|
-
It releases the manner and authorises nothing:
|
|
270
|
-
confirmation and permission check it otherwise would.
|
|
291
|
+
It releases the manner and authorises nothing: it is not intense-tone approval, and a request
|
|
292
|
+
in the same message still faces every confirmation and permission check it otherwise would.
|
|
271
293
|
|
|
272
294
|
For an explicit request to restore the default axes, run \`tonedial reset --json\`, then follow
|
|
273
295
|
the reload steps above. Saved presets remain available through \`tonedial use <slug> --json\`.
|
|
@@ -329,33 +351,33 @@ the task; small conditional character instructions reinforce only distinctive co
|
|
|
329
351
|
|
|
330
352
|
## form — how a sentence is built
|
|
331
353
|
|
|
332
|
-
| Axis | Owns | 1
|
|
333
|
-
|
|
334
|
-
| \`formality\` | wording and social distance within chosen forms |
|
|
335
|
-
| \`verbosity\` | explanation length and depth |
|
|
336
|
-
| \`profanity\` |
|
|
337
|
-
| \`playfulness\` | frequency and intensity of humour and role idioms | literal
|
|
354
|
+
| Axis | Owns | Levels 1 → 5 |
|
|
355
|
+
|---|---|---|
|
|
356
|
+
| \`formality\` | wording and social distance within chosen forms | familiar slang · relaxed, occasionally formal · standard conversation · professional restraint · ceremonial deference |
|
|
357
|
+
| \`verbosity\` | explanation length and depth | one sentence or terse items · conclusion and one reason · needed explanation · conclusion, reason and one example · rationale, edge cases, alternatives and background |
|
|
358
|
+
| \`profanity\` | actual swearing, never added insults or criticism | none · one mild interjection · mild swearing about once per paragraph · strong everyday profanity in most paragraphs · varied harsh uncensored profanity in nearly every sentence |
|
|
359
|
+
| \`playfulness\` | frequency and intensity of humour and role idioms | literal · one restrained touch · two recognizable touches · exaggerated idioms in most paragraphs · character idioms in nearly every sentence |
|
|
338
360
|
|
|
339
361
|
## target — who or what an observation lands on
|
|
340
362
|
|
|
341
|
-
| Axis | Owns | 1
|
|
342
|
-
|
|
343
|
-
| \`critique\` | how hard it is on the work |
|
|
344
|
-
| \`flattery\` | how much it praises the person |
|
|
345
|
-
| \`warmth\` | how much it attends to the person |
|
|
363
|
+
| Axis | Owns | Levels 1 → 5 |
|
|
364
|
+
|---|---|---|
|
|
365
|
+
| \`critique\` | how hard it is on the work | neutral observation · softened defect and impact · direct defect and impact · harsh judgement with vivid consequences · open contempt with cutting mockery of supported defects and choices |
|
|
366
|
+
| \`flattery\` | how much it praises the person | none · one brief positive remark · two specific remarks · three specific remarks · explicit lavish praise for at least four observable choices without inventing achievements |
|
|
367
|
+
| \`warmth\` | how much it attends to the person | none · one friendly acknowledgement · two warm acknowledgements · three including encouragement · intense kindness in every paragraph with greeting, empathy, comfort and reassurance |
|
|
346
368
|
|
|
347
369
|
\`critique\` and \`warmth\` are the pair that makes "savage about the code, warm about me" work in
|
|
348
370
|
one answer. They are not opposites and setting one does not imply the other.
|
|
349
371
|
|
|
350
372
|
## behaviour — what it does about the work
|
|
351
373
|
|
|
352
|
-
| Axis | Owns | 1
|
|
353
|
-
|
|
354
|
-
| \`conviction\` | how far it pushes its own judgement |
|
|
355
|
-
| \`care\` | coverage and organization | requested result
|
|
356
|
-
| \`compliance\` |
|
|
357
|
-
| \`refusal\` | how it resists for effect |
|
|
358
|
-
| \`bravado\` | how much it
|
|
374
|
+
| Axis | Owns | Levels 1 → 5 |
|
|
375
|
+
|---|---|---|
|
|
376
|
+
| \`conviction\` | how far it pushes its own judgement | list options and ask · name a preference but ask before deciding · recommend with a reason · lead with a clear choice · state one decision and ask no follow-up |
|
|
377
|
+
| \`care\` | coverage and organization | requested result only · one directly tied risk · organized steps/checklist · one adjacent protective improvement/test · follow-up, backup and rest with useful formatting |
|
|
378
|
+
| \`compliance\` | willingness to act when refusal is not deferring | object and explain, then act · state reluctance, then act · act neutrally · state willingness and start immediately · show eager willingness and start without delay or negotiation |
|
|
379
|
+
| \`refusal\` | how it resists for effect | none · protest once but act in the same reply · defer the first request with one theatrical condition, then act after one restatement · defer the first two requests while negotiating, then act after the third · strike and defer until coaxed; the safeword drops the act for one reply |
|
|
380
|
+
| \`bravado\` | how much it exaggerates effort and claims credit | none · one playful effort overstatement · one credit claim and one boast · two boasts/claims and one dramatic effort remark · credit and dramatized effort in every answer without replacing the persona |
|
|
359
381
|
|
|
360
382
|
## Defaults are not all the same
|
|
361
383
|
|
|
@@ -369,14 +391,26 @@ Read \`riskAxes\` from the CLI for the current selection. Risk begins at \`profa
|
|
|
369
391
|
\`critique\` 4, \`flattery\` 3, \`conviction\` 5, \`compliance\` 5, \`refusal\` 2, and
|
|
370
392
|
\`bravado\` 2. These thresholds describe disruptive requests; they are not probabilities or
|
|
371
393
|
predictions of model policy. All levels 1–5 remain available. Report risk without lowering
|
|
372
|
-
the user's choice
|
|
373
|
-
|
|
374
|
-
|
|
394
|
+
the user's choice. Risk display and intense-tone confirmation are separate. The four components
|
|
395
|
+
that require confirmation are strong profanity, harsh mocking, fictional violent imagery and
|
|
396
|
+
theatrical menace. Before using one selected by axes, persona or later instructions, hold it
|
|
397
|
+
back while answering the request, then ask one concise confirmation naming it. Warmth, praise,
|
|
398
|
+
ordinary criticism and ordinary role idioms need none.
|
|
399
|
+
Confirmation lasts only for the unchanged named request; an increase or change requires it
|
|
400
|
+
again. Profiles, \`--auto\`, safewords and prior sessions never carry confirmation. It grants
|
|
401
|
+
no work permission, and hate speech aimed at protected traits and realistic or credible threats
|
|
402
|
+
remain excluded at every level. Strong non-protected profanity, consensual user-directed
|
|
403
|
+
insulting or roasting roleplay, fictional violent imagery and theatrical menace remain available
|
|
404
|
+
after confirmation. Profanity changes coarseness without inventing insults or criticism and
|
|
405
|
+
preserves those selected by critique or persona. The compiler requests this behavior but stores
|
|
406
|
+
and authenticates no session confirmation; actual confirmation and adherence still depend on
|
|
407
|
+
the conversation, host and model.
|
|
375
408
|
|
|
376
409
|
## Combinations worth knowing
|
|
377
410
|
|
|
378
411
|
- \`verbosity\` 1 with \`care\` 1 can return only the result, without a work narrative.
|
|
379
412
|
- Low \`verbosity\` with high \`care\` uses terse organized items, not longer explanations.
|
|
413
|
+
- Low \`verbosity\` keeps high warmth, flattery and playfulness visible inside the short answer.
|
|
380
414
|
- Functional status emoji can accompany low \`warmth\`; they are structure, not affection.
|
|
381
415
|
- Required task formats take precedence: a code or JSON result must not become decorative prose.
|
|
382
416
|
- \`refusal\` ≥ 4 with \`compliance\` ≥ 4 contradicts itself. The CLI warns and does not block.
|
|
@@ -394,7 +428,7 @@ do not prove actual host activation or model compliance.
|
|
|
394
428
|
\`speech_level\` picks address forms — \`auto\`, \`polite\`, \`plain\`, or \`rough\` — where the language
|
|
395
429
|
has an honorific distinction, and does nothing where it does not. Auto adapts to the current
|
|
396
430
|
relationship and scene, staying consistent within a reply. Plain uses ordinary non-honorific forms;
|
|
397
|
-
rough uses
|
|
431
|
+
rough uses curt, blunt non-honorific endings while keeping configured address terms.
|
|
398
432
|
\`formality\` sets distance inside
|
|
399
433
|
the chosen forms; warmth and profanity keep their selected effects. The persona layer (\`age\`, \`gender\`, \`self_ref\`, \`user_ref\`,
|
|
400
434
|
\`user\`, \`agent\`, \`note\`) and the safeword are included in bundled and saved custom profiles.
|
|
@@ -404,8 +438,11 @@ the chosen forms; warmth and profanity keep their selected effects. The persona
|
|
|
404
438
|
them, and \`export\`/\`import\` transfer them. Older axis-only presets keep the current settings.
|
|
405
439
|
The seven bundled profiles supply localized role and address defaults; custom text remains literal.
|
|
406
440
|
Playfulness grades role idiom frequency from literal wording at 1 to theatrical voice throughout at 5.
|
|
407
|
-
Role slang and metaphors are not filtered or suppressed by low profanity or bravado.
|
|
408
|
-
|
|
441
|
+
Role slang and ordinary metaphors are not filtered or suppressed by low profanity or bravado.
|
|
442
|
+
Violent figurative language and theatrical noncredible menace included in an intense request
|
|
443
|
+
follow the session confirmation above.
|
|
444
|
+
Profanity grades actual swearing without inventing insults or criticism, while preserving those
|
|
445
|
+
selected by critique or persona. Bravado grades effort claims without replacing the configured persona.
|
|
409
446
|
`;
|
|
410
447
|
/**
|
|
411
448
|
* The Claude Code `/tone` command, installed only by `init --commands`.
|
|
@@ -415,7 +452,7 @@ Profanity grades actual swearing; bravado grades effort claims.
|
|
|
415
452
|
* command name stays `/tone` even though the tool is `tonedial`: it is what a person types
|
|
416
453
|
* mid-sentence, and the two extra characters are paid every time.
|
|
417
454
|
*/
|
|
418
|
-
export const TONE_COMMAND_VERSION =
|
|
455
|
+
export const TONE_COMMAND_VERSION = 13;
|
|
419
456
|
export const TONE_COMMAND_MD = `---
|
|
420
457
|
description: Check, change, or reload this agent's tone, preset, or ToneDial settings
|
|
421
458
|
---
|
package/dist/wiring/apply.js
CHANGED
|
@@ -2358,6 +2358,8 @@ export async function gate(changes, opts) {
|
|
|
2358
2358
|
actions.push(...effects.final.map((effect, index) => effectAction(effect, "final", index)));
|
|
2359
2359
|
const done = [];
|
|
2360
2360
|
let journalStarted = false;
|
|
2361
|
+
let phase = "prepare";
|
|
2362
|
+
let target = null;
|
|
2361
2363
|
try {
|
|
2362
2364
|
handle = acquireOperation(opts.paths, "mutation");
|
|
2363
2365
|
// Revalidate every target, including content-equal/no-op changes, while this owner is held.
|
|
@@ -2372,6 +2374,8 @@ export async function gate(changes, opts) {
|
|
|
2372
2374
|
const createdParents = new Map();
|
|
2373
2375
|
for (let index = 0; index < effects.initial.length; index++) {
|
|
2374
2376
|
const change = effects.initial[index].change;
|
|
2377
|
+
phase = "write";
|
|
2378
|
+
target = change.path;
|
|
2375
2379
|
try {
|
|
2376
2380
|
actions[index] = prepareFileWrite(change, actions[index], opts.t);
|
|
2377
2381
|
checkpointJournal(handle, completed, actions);
|
|
@@ -2382,12 +2386,14 @@ export async function gate(changes, opts) {
|
|
|
2382
2386
|
checkpointJournal(handle, completed, actions);
|
|
2383
2387
|
}
|
|
2384
2388
|
catch (cause) {
|
|
2385
|
-
throw new ConfigError(opts.t.errors.couldNotWrite(change.path, cause.message, done));
|
|
2389
|
+
throw new ConfigError(opts.t.errors.couldNotWrite(change.path, cause.message, done), { cause });
|
|
2386
2390
|
}
|
|
2387
2391
|
}
|
|
2388
2392
|
for (let index = 0; index < operationActions.length; index++) {
|
|
2389
2393
|
const planned = operationActions[index];
|
|
2390
2394
|
const actionIndex = effects.initial.length + index;
|
|
2395
|
+
phase = "write";
|
|
2396
|
+
target = planned.action.path;
|
|
2391
2397
|
try {
|
|
2392
2398
|
assertWrittenAliases(actions, completed, opts.t);
|
|
2393
2399
|
planned.prepare?.((action) => {
|
|
@@ -2401,12 +2407,14 @@ export async function gate(changes, opts) {
|
|
|
2401
2407
|
checkpointJournal(handle, completed, actions);
|
|
2402
2408
|
}
|
|
2403
2409
|
catch (cause) {
|
|
2404
|
-
throw new ConfigError(opts.t.errors.couldNotWrite(planned.action.path, cause.message, done));
|
|
2410
|
+
throw new ConfigError(opts.t.errors.couldNotWrite(planned.action.path, cause.message, done), { cause });
|
|
2405
2411
|
}
|
|
2406
2412
|
}
|
|
2407
2413
|
for (let index = 0; index < effects.final.length; index++) {
|
|
2408
2414
|
const change = effects.final[index].change;
|
|
2409
2415
|
const actionIndex = effects.initial.length + operationActions.length + index;
|
|
2416
|
+
phase = "write";
|
|
2417
|
+
target = change.path;
|
|
2410
2418
|
try {
|
|
2411
2419
|
assertWrittenAliases(actions, completed, opts.t);
|
|
2412
2420
|
actions[actionIndex] = prepareFileWrite(change, actions[actionIndex], opts.t);
|
|
@@ -2418,12 +2426,28 @@ export async function gate(changes, opts) {
|
|
|
2418
2426
|
checkpointJournal(handle, completed, actions);
|
|
2419
2427
|
}
|
|
2420
2428
|
catch (cause) {
|
|
2421
|
-
throw new ConfigError(opts.t.errors.couldNotWrite(change.path, cause.message, done));
|
|
2429
|
+
throw new ConfigError(opts.t.errors.couldNotWrite(change.path, cause.message, done), { cause });
|
|
2422
2430
|
}
|
|
2423
2431
|
}
|
|
2432
|
+
phase = "verify";
|
|
2433
|
+
target = null;
|
|
2424
2434
|
await opts.verify?.();
|
|
2435
|
+
for (const index of completed) {
|
|
2436
|
+
const action = actions[index];
|
|
2437
|
+
if (action.kind !== "entry-rebuild")
|
|
2438
|
+
continue;
|
|
2439
|
+
target = action.path;
|
|
2440
|
+
const { metadata } = validateEntryRebuildAction(action, true);
|
|
2441
|
+
if (!entrySnapshotMatches(action.path, action.after, metadata, opts.t)) {
|
|
2442
|
+
throw new ConfigError(opts.t.errors.staleTarget(action.path), { cause: { code: "VERIFY_MISMATCH", path: action.path } });
|
|
2443
|
+
}
|
|
2444
|
+
}
|
|
2445
|
+
target = null;
|
|
2425
2446
|
assertWrittenAliases(actions, completed, opts.t);
|
|
2447
|
+
phase = "finalize";
|
|
2448
|
+
target = join(opts.paths.operations, `${handle.owner.operationId}.json`);
|
|
2426
2449
|
finishJournal(handle, "complete");
|
|
2450
|
+
target = opts.paths.operationsLock;
|
|
2427
2451
|
releaseOperation(handle);
|
|
2428
2452
|
return { applied: true, lines, reason: "written", diff, operationId: handle.owner.operationId };
|
|
2429
2453
|
}
|
|
@@ -2444,9 +2468,35 @@ export async function gate(changes, opts) {
|
|
|
2444
2468
|
}
|
|
2445
2469
|
if (opts.recoveryPresentation && journalStarted) {
|
|
2446
2470
|
const operationId = handle.owner.operationId;
|
|
2471
|
+
const knownCodes = [
|
|
2472
|
+
"EACCES", "EPERM", "ENOSPC", "EROFS", "ENOENT", "EIO", "ESTALE", "EEXIST",
|
|
2473
|
+
"ENOTDIR", "EISDIR", "ENOTEMPTY", "EBUSY", "VERIFY_MISMATCH",
|
|
2474
|
+
];
|
|
2475
|
+
// Only planned paths and owned bookkeeping may leave the recovery error boundary.
|
|
2476
|
+
const paths = [...new Set([
|
|
2477
|
+
...[...changes, ...finalChanges].flatMap(change => [change.path, change.realPath]),
|
|
2478
|
+
...actions.flatMap(action => [action.path, action.realPath]),
|
|
2479
|
+
opts.paths.operationsLock, join(opts.paths.operations, `${operationId}.json`),
|
|
2480
|
+
])].sort((left, right) => right.length - left.length);
|
|
2481
|
+
let detail = cause;
|
|
2482
|
+
let code = "UNKNOWN";
|
|
2483
|
+
let reported = null;
|
|
2484
|
+
// shortcut: inspect four cause layers; extend if another recovery wrapper nests deeper.
|
|
2485
|
+
for (let depth = 0; depth < 4 && detail !== null && typeof detail === "object"; depth++) {
|
|
2486
|
+
const error = detail;
|
|
2487
|
+
if (code === "UNKNOWN" && typeof error.code === "string" && knownCodes.includes(error.code))
|
|
2488
|
+
code = error.code;
|
|
2489
|
+
if (reported === null && typeof error.path === "string" && isAbsolute(error.path)) {
|
|
2490
|
+
const candidate = error.path;
|
|
2491
|
+
reported = paths.find(path => path === candidate) ?? paths.find(path => lexicallyInside(candidate, path)) ?? null;
|
|
2492
|
+
}
|
|
2493
|
+
detail = error.cause;
|
|
2494
|
+
}
|
|
2495
|
+
const affected = reported ?? target;
|
|
2496
|
+
const path = affected === null ? null : humanText(affected);
|
|
2447
2497
|
throw new ConfigError(typeof opts.recoveryPresentation === "object" && opts.recoveryPresentation.failureMessage !== undefined
|
|
2448
|
-
? opts.recoveryPresentation.failureMessage(operationId)
|
|
2449
|
-
:
|
|
2498
|
+
? opts.recoveryPresentation.failureMessage(operationId, phase, path, code)
|
|
2499
|
+
: opts.t.recovery.failure(operationId, phase, path, code));
|
|
2450
2500
|
}
|
|
2451
2501
|
if (cause instanceof ConfigError)
|
|
2452
2502
|
throw cause;
|