tonedial 0.1.2 → 0.1.4
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/cli.js +22 -8
- package/dist/commands/doctor.js +27 -4
- package/dist/commands/get.js +41 -0
- package/dist/commands/rebuild.js +37 -16
- package/dist/commands/save.js +1 -1
- package/dist/commands/set.js +12 -26
- package/dist/commands/show.js +24 -19
- package/dist/core/anchors.js +1 -0
- package/dist/core/compile.js +2 -2
- package/dist/core/config.js +20 -8
- package/dist/core/i18n.js +32 -18
- package/dist/core/legacy-tone.js +6 -4
- package/dist/core/locales/es.js +16 -9
- package/dist/core/locales/ja.js +16 -9
- package/dist/core/locales/zh.js +16 -9
- package/dist/core/presets.js +3 -0
- package/dist/core/seeds.js +3 -3
- package/dist/core/selfupdate.js +25 -4
- package/dist/core/skill.js +33 -12
- package/dist/wiring/apply.js +55 -5
- package/package.json +1 -1
package/dist/core/skill.js
CHANGED
|
@@ -29,7 +29,14 @@ or repair decision. Never edit or recreate them directly.
|
|
|
29
29
|
/** Both entry points distinguish current tone settings from saved profiles. */
|
|
30
30
|
const PRESETS_MD = `## Current settings and saved presets
|
|
31
31
|
|
|
32
|
-
\`tonedial
|
|
32
|
+
\`tonedial get --json\` reports the current editable settings in a flat \`values\` object.
|
|
33
|
+
\`get <key> --json\` selects one of those keys, preserving numbers, literal text and nulls.
|
|
34
|
+
The keys are the twelve axes, \`language\`, \`speech_level\`, \`safeword\`, and
|
|
35
|
+
\`persona.age\`, \`persona.gender\`, \`persona.self_ref\`, \`persona.user_ref\`,
|
|
36
|
+
\`persona.note\`, \`persona.user\`, and \`persona.agent\`.
|
|
37
|
+
\`language\` selects the CLI interface, not the agent's reply language.
|
|
38
|
+
Read-only \`get\` neither changes settings nor reloads this conversation.
|
|
39
|
+
\`tonedial show --json\` adds the overview and artifact metadata. \`show <slug> --json\` previews that
|
|
33
40
|
preset's saved tone settings. \`unsaved\` on the current result means the current tone settings
|
|
34
41
|
have not been saved back to a profile; the current configuration itself is persisted.
|
|
35
42
|
For an explicit request to save a profile, use \`tonedial save "<display name>" --json\`.
|
|
@@ -107,6 +114,7 @@ interpolating it into shell code.
|
|
|
107
114
|
| Persona manner or role note | \`tonedial set "persona.note=Patient guide" --json\` |
|
|
108
115
|
| Safeword phrase | \`tonedial set "safeword=plain answer please" --json\` |
|
|
109
116
|
| Honorific register system | \`tonedial set speech_level=polite --json\` |
|
|
117
|
+
| Rough, cheeky non-honorific endings | \`tonedial set speech_level=rough --json\` |
|
|
110
118
|
|
|
111
119
|
Age bands are \`unspecified\`, \`teens\`, \`20s\`, \`30s\`, \`40s\`, and \`50s+\`.
|
|
112
120
|
Gender values are \`unspecified\`, \`masculine\`, \`feminine\`, and \`neutral\`.
|
|
@@ -127,9 +135,11 @@ ToneDial has no guard toggle or automatic emergency register. All axis levels 1
|
|
|
127
135
|
the user can request. Report advisory \`riskAxes\` and combination notices without lowering
|
|
128
136
|
values, blocking the change, or asking for additional tone-risk confirmation. The host's task
|
|
129
137
|
and permission rules still apply independently.
|
|
130
|
-
For \`speech_level\`, choose \`polite\`, \`plain\`, or \`
|
|
138
|
+
For \`speech_level\`, choose \`auto\`, \`polite\`, \`plain\`, or \`rough\` only when the user requests that
|
|
131
139
|
register system. \`auto\` chooses address forms for the current relationship and scene,
|
|
132
140
|
keeping them consistent within each reply; \`polite\` and \`plain\` fix those forms.
|
|
141
|
+
\`plain\` means ordinary non-honorific forms; \`rough\` requests rough, cheeky non-honorific
|
|
142
|
+
sentence endings. Preserve the configured address terms and every independent axis.
|
|
133
143
|
It has no effect where the language lacks an honorific distinction. A request for more or
|
|
134
144
|
less formality changes wording and distance within the chosen forms, without silently changing
|
|
135
145
|
\`speech_level\`. Familiar polite, formal plain and affectionate swearing are valid combinations;
|
|
@@ -167,6 +177,14 @@ an active association needs the user's explicit choice and must not reset saved
|
|
|
167
177
|
Do not edit files, change the state root, remove locks or grant hook trust yourself.
|
|
168
178
|
The user chooses native tools and scope separately; foreign provider containers are not
|
|
169
179
|
application outputs. A successful app rebuild can still report native attention.
|
|
180
|
+
If repair fails, report its phase, affected path, safe error code and operation ID.
|
|
181
|
+
Some file changes may already be applied; a failure is not evidence that all files stayed unchanged.
|
|
182
|
+
Preserve the operation record and follow the reported scoped read-only diagnosis.
|
|
183
|
+
Default doctor output focuses on blockers; \`--verbose\` and JSON retain the operation history.
|
|
184
|
+
For an explicitly selected stopped operation, \`doctor --fix --from-operation <id>\` continues
|
|
185
|
+
application repair using valid current settings first; it does not undo the earlier changes.
|
|
186
|
+
Preview that exact ID and scope with \`--dry-run\` before applying the approved repair.
|
|
187
|
+
Interactive selection requires the full displayed ID; Enter cancels without writing.
|
|
170
188
|
\`doctor --fix --dry-run\` previews app and selected native changes without writing or
|
|
171
189
|
printing private prior values. Keep both reported IDs when recovery changes app and native
|
|
172
190
|
files; follow the receipt and roll back native connections before application files.
|
|
@@ -198,12 +216,13 @@ the user to complete CLI installation and explicit setup; do not install it or g
|
|
|
198
216
|
## Read the current state first
|
|
199
217
|
|
|
200
218
|
\`\`\`bash
|
|
201
|
-
tonedial
|
|
219
|
+
tonedial get --json
|
|
202
220
|
\`\`\`
|
|
203
221
|
|
|
204
|
-
The
|
|
205
|
-
|
|
206
|
-
\`
|
|
222
|
+
The \`values\` object carries the twelve axis levels and the separate settings under their
|
|
223
|
+
editable keys. An unset setting is \`null\`; description text is returned in full.
|
|
224
|
+
For the formatted overview, preset state and advisory \`riskAxes\`, use \`tonedial show --json\`.
|
|
225
|
+
Every command takes \`--json\` and answers with a \`schema\` field.
|
|
207
226
|
${JSON_MD}
|
|
208
227
|
Otherwise report the failed step
|
|
209
228
|
and stop that flow. Never report a failed mutation as saved; failures after a successful mutation
|
|
@@ -230,7 +249,7 @@ Report the movement back to the user in their own terms, from the \`moves\` fiel
|
|
|
230
249
|
- "stop flattering me" → \`flattery=1\`. Not \`warmth\`, which is a different observable.
|
|
231
250
|
- "be brief" → \`verbosity\` down. Change \`care\` only for requested coverage or organization changes.
|
|
232
251
|
- "more casual" → \`formality\` down. Change the register system only on an explicit request,
|
|
233
|
-
such as "use plain forms" → \`speech_level=plain\`.
|
|
252
|
+
such as "use plain forms" → \`speech_level=plain\`, or "use rough, cheeky plain forms" → \`speech_level=rough\`.
|
|
234
253
|
|
|
235
254
|
For a named preset, run \`tonedial list --json\` then \`tonedial use <slug> --json\`.
|
|
236
255
|
An explicit agent character or role request uses \`persona.agent\`; an explicit request to
|
|
@@ -308,7 +327,7 @@ During a test conversation, do not mutate ToneDial settings or perform work thro
|
|
|
308
327
|
*/
|
|
309
328
|
export const SKILL_TRAITS_MD = `# Axes
|
|
310
329
|
|
|
311
|
-
Twelve axes, each 1 to 5. Read the live values with \`tonedial
|
|
330
|
+
Twelve axes, each 1 to 5. Read the live values with \`tonedial get --json\`; this file says what
|
|
312
331
|
each one **owns**, which is what tells you which axis a request is actually about.
|
|
313
332
|
|
|
314
333
|
Axes name distinct aspects of a reply. Map the aspect the user named rather than changing
|
|
@@ -380,9 +399,11 @@ do not prove actual host activation or model compliance.
|
|
|
380
399
|
|
|
381
400
|
## Settings that are not axes
|
|
382
401
|
|
|
383
|
-
\`speech_level\` picks address forms — \`auto\`, \`polite\`, or \`
|
|
402
|
+
\`speech_level\` picks address forms — \`auto\`, \`polite\`, \`plain\`, or \`rough\` — where the language
|
|
384
403
|
has an honorific distinction, and does nothing where it does not. Auto adapts to the current
|
|
385
|
-
relationship and scene, staying consistent within a reply.
|
|
404
|
+
relationship and scene, staying consistent within a reply. Plain uses ordinary non-honorific forms;
|
|
405
|
+
rough uses rough, cheeky non-honorific endings while keeping configured address terms.
|
|
406
|
+
\`formality\` sets distance inside
|
|
386
407
|
the chosen forms; warmth and profanity keep their selected effects. The persona layer (\`age\`, \`gender\`, \`self_ref\`, \`user_ref\`,
|
|
387
408
|
\`user\`, \`agent\`, \`note\`) and the safeword are included in bundled and saved custom profiles.
|
|
388
409
|
\`persona.user\` is user context and \`persona.agent\` a fictional agent role, each limited to
|
|
@@ -402,12 +423,12 @@ Profanity grades actual swearing; bravado grades effort claims.
|
|
|
402
423
|
* command name stays `/tone` even though the tool is `tonedial`: it is what a person types
|
|
403
424
|
* mid-sentence, and the two extra characters are paid every time.
|
|
404
425
|
*/
|
|
405
|
-
export const TONE_COMMAND_VERSION =
|
|
426
|
+
export const TONE_COMMAND_VERSION = 12;
|
|
406
427
|
export const TONE_COMMAND_MD = `---
|
|
407
428
|
description: Check, change, or reload this agent's tone, preset, or ToneDial settings
|
|
408
429
|
---
|
|
409
430
|
|
|
410
|
-
Run \`tonedial
|
|
431
|
+
Run \`tonedial get --json\` and report the requested current settings from \`values\` in plain language.
|
|
411
432
|
Use the same installed CLI and environment throughout.
|
|
412
433
|
${JSON_MD}
|
|
413
434
|
Otherwise report the failed step and stop that flow.
|
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;
|