tonedial 0.1.6 → 0.1.7

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.
@@ -26,6 +26,14 @@ const messages = {
26
26
  launchFailed: (provider) => `无法启动 ${provider}。请检查安装情况后重试。`,
27
27
  selectionCancelled: "未选择服务商。",
28
28
  },
29
+ delivery: {
30
+ on: "ToneDial 已开启 · 已清除暂停投递标记",
31
+ off: "ToneDial 已关闭 · 已保存暂停投递标记 · 保留设置和 TONE.md",
32
+ alreadyOn: "语气投递已处于开启状态 · 无变更",
33
+ alreadyOff: "语气投递已处于关闭状态 · 无变更",
34
+ openConversation: "已打开的对话可能保留之前的语气。请用新对话准确比较未使用 ToneDial 的状态。",
35
+ status: (enabled) => `语气投递${enabled ? "已开启" : "已关闭"}`,
36
+ },
29
37
  axis: {
30
38
  range: (axis, given) => `${axis}:应为 1–5(收到 ${given})`,
31
39
  unknown: (name, nearest) => `${name}:不是语气轴${nearest ? `。是否想输入 ${nearest}?` : ""}`,
@@ -428,6 +436,8 @@ const messages = {
428
436
  firstSteps: "设置语气后检查:",
429
437
  examples: "示例",
430
438
  commands: {
439
+ on: "恢复投递已保存的语气",
440
+ off: "暂停语气投递 · 保留设置和 TONE.md",
431
441
  init: "初始化并刷新内置文件",
432
442
  set: "修改语气轴、角色或设置 · 无参数打开面板",
433
443
  get: "读取当前设置值 · 指定键可查看含义和选项",
@@ -486,10 +496,9 @@ const messages = {
486
496
  errors: {
487
497
  notACommand: (name, known, nearest) => `${name} 不是命令。${nearest ? `是否想输入 ${nearest}?` : ""} ` +
488
498
  `可用命令:${known.join(", ")}`,
489
- noOffSwitch: "没有关闭开关。设置安全词后可请求一次平实回答;用 tonedial show 检查是否已设置。" +
490
- "tonedial reset 恢复语气轴默认值。tonedial eject --global 或 " +
491
- "--project <path> 断开对应范围。移除全部连接后," +
492
- "npm uninstall -g tonedial 可移除命令。",
499
+ stoppingHelp: "要在不删除设置的情况下暂停语气投递,请运行 tonedial off;运行 tonedial on 可恢复投递。" +
500
+ "tonedial reset 恢复语气轴默认值。tonedial eject --global 或 --project <path> 会断开该范围的连接。" +
501
+ "断开所有连接后,可用 npm uninstall -g tonedial 删除命令。",
493
502
  notAnOption: (flag) => `${flag}:不是选项。列表:tonedial --help`,
494
503
  flagNotAccepted: (command, flag) => `${command}:不接受 --${flag}`,
495
504
  tooManyArguments: (command, max, got) => `${command}:最多 ${max} 个参数,收到 ${got} 个`,
@@ -1,6 +1,7 @@
1
1
  // Hooks may run without PATH or after the package moves. The seeded reader is standalone.
2
2
  import { CONTEXT_ARTIFACT_FILENAME, CONTEXT_GUIDE_FILENAME, } from "./paths.js";
3
- export const READER_PROTOCOL_VERSION = 2;
3
+ import { DELIVERY_OFF_MARKER } from "./anchors.js";
4
+ export const READER_PROTOCOL_VERSION = 3;
4
5
  export const GUIDE_FORMAT_VERSION = 1;
5
6
  export const GUIDE_FORMAT_MARKER = `<!-- tonedial-guide:${GUIDE_FORMAT_VERSION} -->`;
6
7
  /** Stable, short repair guidance shared by the emitted source and diagnostics. */
@@ -25,6 +26,7 @@ export const READER_REPAIR_HINTS = {
25
26
  event: "use a supported hook event",
26
27
  input: "retry the hook with a valid event payload",
27
28
  response: "retry the hook when the response is available",
29
+ "delivery-marker": "regenerate the tone artifact",
28
30
  "style-marker": "regenerate the tone artifact",
29
31
  unreadable: "run tonedial doctor and resolve the reported path",
30
32
  };
@@ -50,6 +52,7 @@ const GUIDE_FILENAME = ${JSON.stringify(CONTEXT_GUIDE_FILENAME)};
50
52
  const ARTIFACT_FILENAME = ${JSON.stringify(CONTEXT_ARTIFACT_FILENAME)};
51
53
  const LOCK_FILENAME = "operations.lock";
52
54
  const GUIDE_MARKER = ${JSON.stringify(GUIDE_FORMAT_MARKER)};
55
+ const DELIVERY_OFF_MARKER = ${JSON.stringify(DELIVERY_OFF_MARKER)};
53
56
  const REPAIR_HINTS = ${JSON.stringify(READER_REPAIR_HINTS)};
54
57
  const PROVIDERS = new Set(["codex", "claude", "antigravity"]);
55
58
  const EVENTS = new Set(["SessionStart", "UserPromptSubmit", "Stop", "PreInvocation"]);
@@ -338,6 +341,13 @@ function styleMarker(artifact) {
338
341
  return match === null ? null : { verbosity: Number(match[1]), care: Number(match[2]) };
339
342
  }
340
343
 
344
+ function deliveryEnabled(artifact) {
345
+ const line = artifact.split(/\r?\n/, 3)[2] ?? "";
346
+ if (line === DELIVERY_OFF_MARKER) return false;
347
+ if (line.startsWith("<!-- tonedial-delivery:")) throw new ReaderFailure("delivery-marker");
348
+ return true;
349
+ }
350
+
341
351
  // shortcut: ambiguous data-like prose skips feedback; refine only with verified host format metadata.
342
352
  function literalPayload(text) {
343
353
  const value = text.trim();
@@ -400,8 +410,12 @@ async function main() {
400
410
  const hint = providerHint(args);
401
411
  try {
402
412
  const { provider, state, event } = parseArgs(args);
403
- const input = event === "Stop" ? await hookInput() : null;
404
413
  const pair = readPair(state);
414
+ if (!deliveryEnabled(pair.artifact)) {
415
+ empty(provider, event);
416
+ return;
417
+ }
418
+ const input = event === "Stop" ? await hookInput() : null;
405
419
  if (event === "Stop") {
406
420
  const result = styleFeedback(pair, input);
407
421
  if (result.diagnostic !== null) {
@@ -5,6 +5,7 @@ export function toCompileInput(stored) {
5
5
  // The slug rides in the generation comment, so the model reads it. `unsaved` is what the
6
6
  // artifact says once tone settings have moved away from the profile that named them.
7
7
  preset: stored.unsaved ? null : stored.preset,
8
+ ...(stored.enabled ? {} : { enabled: false }),
8
9
  axes: stored.axes,
9
10
  speech_level: stored.speech_level,
10
11
  persona: hasPersona ? p : null,
@@ -11,13 +11,13 @@ import { captureRawEntry, caseRenameMatchesCurrent, isNoop, planChange, planEntr
11
11
  import { BUNDLED, builtinPresetDir, LEGACY_BUILTIN_SLUGS, RETIRED_PRESETS } from "./presets.js";
12
12
  import { SKILL_MD, SKILL_NAME, SKILL_TRAITS_MD } from "./skill.js";
13
13
  // Bump for changed generated content; freshness also checks each managed seed's bytes/provenance.
14
- export const SEED_VERSION = 23;
14
+ export const SEED_VERSION = 24;
15
15
  /** The state-root operating boundaries. The compiler owns the current tone separately. */
16
16
  export const GUIDE_MD = `${GUIDE_FORMAT_MARKER}
17
17
  ToneDial changes manner only; it never expands task scope or permissions.
18
18
  Use the ToneDial CLI for configuration changes.
19
19
  AGENTS.md is the operating guide, TONE.md is the current compiled tone, and the ToneDial skill
20
- explains explicit in-session tuning and reloads.
20
+ explains delivery controls, explicit in-session tuning and reloads.
21
21
  `;
22
22
  /** Existing generated runtime families are repaired without inferring any native connection. */
23
23
  export function generatedSeedSelection(paths, config, native, t = catalogue("en").cli) {
@@ -73,7 +73,7 @@ export function seedFiles(paths, selection) {
73
73
  };
74
74
  const native = [
75
75
  reader,
76
- { id: "skill/body", version: 21, path: join(paths.skill, SKILL_NAME, "SKILL.md"), label: `skill/${SKILL_NAME}/SKILL.md`, contents: SKILL_MD },
76
+ { id: "skill/body", version: 22, path: join(paths.skill, SKILL_NAME, "SKILL.md"), label: `skill/${SKILL_NAME}/SKILL.md`, contents: SKILL_MD },
77
77
  {
78
78
  id: "skill/traits",
79
79
  version: 12,
@@ -5,6 +5,7 @@ export const SKILL_NAME = "tonedial";
5
5
  /** The current command envelope, shared by both installed control entry points. */
6
6
  const JSON_MD = `Require zero exit status and a JSON result with \`ok: true\` and \`schema: 3\`
7
7
  for every successful CLI step before continuing. Parse JSON rather than scraping human output.
8
+ \`get --json\`, \`show --json\`, and \`compile --check --json\` report the shared \`enabled\` delivery state.
8
9
  \`chars\` reports the current TONE.md Unicode character count; no size target or maximum applies.
9
10
  Schema 3 removes guard and ceiling fields and reports advisory \`riskAxes\`; persisted config
10
11
  remains schema 2. Custom profiles use preset schema 2; legacy schema 1 and journal formats
@@ -65,6 +66,10 @@ Require zero exit status, \`ok: true\`, and \`schema: 3\` before continuing.
65
66
  This read-only command reports destinations; it does not prove that either file exists,
66
67
  matches the saved settings, or has been loaded.
67
68
 
69
+ If it reports \`enabled: false\`, do not read or apply the context pair. Report that the settings
70
+ are saved but delivery remains off. This also applies to tone changes made while delivery is off.
71
+ Continue below only when it reports \`enabled: true\`.
72
+
68
73
  Read the complete UTF-8 file at the returned absolute \`agentsPath\` first (\`AGENTS.md\`).
69
74
  Its first line must be \`${GUIDE_FORMAT_MARKER}\`; otherwise stop the reload.
70
75
  Then read the complete UTF-8 file at the returned absolute \`path\` (\`TONE.md\`).
@@ -86,6 +91,22 @@ This reload affects only the current conversation. It does not fire a lifecycle
86
91
  earlier context, or reload other open sessions. Future delivery still depends on an installed,
87
92
  enabled, and trusted native hook.
88
93
  `;
94
+ const DELIVERY_MD = `## Pause and resume delivery
95
+
96
+ For an explicit request to turn ToneDial off, run \`tonedial off --json\`, then run
97
+ \`tonedial compile --check --json\`. Require both results to report \`enabled: false\`.
98
+ Do not read the guide or artifact afterward. Report that saved settings, profiles and the full
99
+ \`TONE.md\` remain. The current ToneDial reader emits no ToneDial context.
100
+ Already delivered context cannot be removed from an open conversation; stop applying the saved
101
+ manner where possible and name a fresh conversation as the clean check. Do not promise a perfect reset.
102
+ The successful command proves the marker was saved, not that a native reader ran.
103
+ A reader installed before this switch must be refreshed through the user's existing tools and scope
104
+ before it can honor the marker.
105
+
106
+ For an explicit request to turn ToneDial on, run \`tonedial on --json\`, then follow the reload
107
+ procedure below. Turning delivery on does not prove that a native hook is installed, trusted,
108
+ enabled or running. Neither command changes axes, persona, address, register, safeword or profiles.
109
+ `;
89
110
  /** Explicit setting requests use the same CLI mapping through either installed entry point. */
90
111
  const SETTINGS_MD = `## Explicit settings
91
112
 
@@ -220,7 +241,7 @@ Do not claim that setup, repair, or migration proves host activation or model ad
220
241
  */
221
242
  export const SKILL_MD = `---
222
243
  name: tonedial
223
- description: Use when the user wants to check, change, or reload ToneDial manner, tone, personality, register, preset, user description, agent role, address terms, or safeword — including requests like "be gentler", "act as a database specialist", "remember my background in ToneDial", "more formal", "call me friend", or asking what the current tone settings are.
244
+ description: Use when the user wants to check, change, pause, resume, or reload ToneDial manner, tone, personality, register, preset, user description, agent role, address terms, or safeword — including requests like "turn ToneDial off", "be gentler", "act as a database specialist", "remember my background in ToneDial", "more formal", "call me friend", or asking what the current tone settings are.
224
245
  ---
225
246
 
226
247
  # tonedial
@@ -239,6 +260,7 @@ the user to complete CLI installation and explicit setup; do not install it or g
239
260
  tonedial get --json
240
261
  \`\`\`
241
262
 
263
+ The top-level \`enabled\` field reports whether native delivery is on.
242
264
  The \`values\` object carries the twelve axis levels and the separate settings under their
243
265
  editable keys. An unset setting is \`null\`; description text is returned in full.
244
266
  For the formatted overview, preset state and advisory \`riskAxes\`, use \`tonedial show --json\`.
@@ -283,9 +305,11 @@ ${SETTINGS_MD}
283
305
 
284
306
  ${SETUP_MD}
285
307
 
308
+ ${DELIVERY_MD}
309
+
286
310
  ## Apply it in this session
287
311
 
288
- Successful \`set\`, \`address\`, \`persona\`, \`use\`, \`reset\`, \`save\`, and approved \`create\` commands recompile \`TONE.md\`; that is a saved state
312
+ Successful \`on\`, \`off\`, \`set\`, \`address\`, \`persona\`, \`use\`, \`reset\`, \`save\`, and approved \`create\` commands recompile \`TONE.md\`; that is a saved state
289
313
  change, not evidence of a session reload.
290
314
 
291
315
  ${RELOAD_MD}
@@ -300,9 +324,9 @@ in the same message still faces every confirmation and permission check it other
300
324
  For an explicit request to restore the default axes, run \`tonedial reset --json\`, then follow
301
325
  the reload steps above. Saved presets remain available through \`tonedial use <slug> --json\`.
302
326
  Reset restores axes only; it does not disable hooks, unload instructions, or clear persona,
303
- safeword, or other settings. ToneDial has no persistent tone-off switch.
304
- For "turn tone off" or an ambiguous "go back to normal", explain that limit and ask whether
305
- the user wants an axis reset before changing state; do not silently equate off with reset.
327
+ safeword, or other settings. Use \`tonedial off --json\` to pause delivery without changing them.
328
+ For an ambiguous "go back to normal", ask whether the user means delivery off or an axis reset;
329
+ do not silently equate them.
306
330
 
307
331
  ## A separate test conversation
308
332
 
@@ -458,12 +482,13 @@ selected by critique or persona. Bravado grades effort claims without replacing
458
482
  * command name stays `/tone` even though the tool is `tonedial`: it is what a person types
459
483
  * mid-sentence, and the two extra characters are paid every time.
460
484
  */
461
- export const TONE_COMMAND_VERSION = 15;
485
+ export const TONE_COMMAND_VERSION = 16;
462
486
  export const TONE_COMMAND_MD = `---
463
- description: Check, change, or reload this agent's tone, preset, or ToneDial settings
487
+ description: Check, change, pause, resume, or reload this agent's tone, preset, or ToneDial settings
464
488
  ---
465
489
 
466
- Run \`tonedial get --json\` and report the requested current settings from \`values\` in plain language.
490
+ Run \`tonedial get --json\` and report the requested current settings from \`values\` and the
491
+ delivery state from \`enabled\` in plain language.
467
492
  Use the same installed CLI and environment throughout.
468
493
  ${JSON_MD}
469
494
  Otherwise report the failed step and stop that flow.
@@ -485,13 +510,15 @@ ${SETTINGS_MD}
485
510
 
486
511
  ${SETUP_MD}
487
512
 
513
+ ${DELIVERY_MD}
514
+
488
515
  ${RELOAD_MD}
489
516
 
490
517
  An explicit axis-reset request uses \`tonedial reset --json\` followed by the same reload steps.
491
518
  Reset restores axes only; it does not disable hooks, unload instructions, or clear persona,
492
519
  safeword, or other settings. Saved presets remain available.
493
- \`/tone off\` is not a persistent tone-off switch. Explain that limit and ask whether the user
494
- wants an axis reset before changing state; never silently equate off with reset.
520
+ For an ambiguous \`/tone normal\`, ask whether the user means delivery off or an axis reset;
521
+ never silently equate them.
495
522
 
496
523
  Never edit ToneDial's config, guide, or artifact directly; the CLI is the source of truth.
497
524
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tonedial",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Set a coding agent's manner once and keep it across every project.",
5
5
  "license": "MIT",
6
6
  "type": "module",