dsh-ssh-tui 0.6.4 → 0.7.0-rc.2

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.
Files changed (79) hide show
  1. package/README.en.md +14 -0
  2. package/README.md +14 -0
  3. package/docs/remote-ops.md +133 -0
  4. package/docs/screenshots/compare.png +0 -0
  5. package/docs/screenshots/headless.png +0 -0
  6. package/docs/screenshots/workspace.png +0 -0
  7. package/lib/approval-cache.js +158 -0
  8. package/lib/approval-cache.js.map +1 -0
  9. package/lib/attach.js +66 -7
  10. package/lib/attach.js.map +1 -1
  11. package/lib/auto-approval.js +13 -0
  12. package/lib/auto-approval.js.map +1 -1
  13. package/lib/color-depth.js +192 -0
  14. package/lib/color-depth.js.map +1 -0
  15. package/lib/commands.js +5 -0
  16. package/lib/commands.js.map +1 -1
  17. package/lib/copy-text.js +1 -0
  18. package/lib/copy-text.js.map +1 -1
  19. package/lib/dialogs.js +81 -8
  20. package/lib/dialogs.js.map +1 -1
  21. package/lib/display-sock.js +24 -8
  22. package/lib/display-sock.js.map +1 -1
  23. package/lib/doctor.js +380 -0
  24. package/lib/doctor.js.map +1 -0
  25. package/lib/footer.js +76 -6
  26. package/lib/footer.js.map +1 -1
  27. package/lib/i18n/en.js +136 -3
  28. package/lib/i18n/en.js.map +1 -1
  29. package/lib/i18n/zh.js +137 -4
  30. package/lib/i18n/zh.js.map +1 -1
  31. package/lib/index.js +8 -1
  32. package/lib/index.js.map +1 -1
  33. package/lib/keymap.js +172 -0
  34. package/lib/keymap.js.map +1 -0
  35. package/lib/line-diff.js +224 -0
  36. package/lib/line-diff.js.map +1 -0
  37. package/lib/line-mode.js +86 -0
  38. package/lib/line-mode.js.map +1 -0
  39. package/lib/paint.js +158 -26
  40. package/lib/paint.js.map +1 -1
  41. package/lib/plan.js +51 -8
  42. package/lib/plan.js.map +1 -1
  43. package/lib/preset-authoring.js +110 -0
  44. package/lib/preset-authoring.js.map +1 -0
  45. package/lib/preset-picker.js +105 -0
  46. package/lib/preset-picker.js.map +1 -0
  47. package/lib/preset-rows.js +288 -34
  48. package/lib/preset-rows.js.map +1 -1
  49. package/lib/selection.js +154 -0
  50. package/lib/selection.js.map +1 -0
  51. package/lib/term-text.js +106 -1
  52. package/lib/term-text.js.map +1 -1
  53. package/lib/tool-present.js +157 -21
  54. package/lib/tool-present.js.map +1 -1
  55. package/lib/tui.js +1428 -97
  56. package/lib/tui.js.map +1 -1
  57. package/lib/types/approval-cache.d.ts +125 -0
  58. package/lib/types/attach.d.ts +29 -0
  59. package/lib/types/auto-approval.d.ts +11 -0
  60. package/lib/types/color-depth.d.ts +50 -0
  61. package/lib/types/commands.d.ts +9 -0
  62. package/lib/types/dialogs.d.ts +36 -5
  63. package/lib/types/display-sock.d.ts +6 -0
  64. package/lib/types/doctor.d.ts +118 -0
  65. package/lib/types/footer.d.ts +35 -0
  66. package/lib/types/keymap.d.ts +68 -0
  67. package/lib/types/line-diff.d.ts +107 -0
  68. package/lib/types/line-mode.d.ts +36 -0
  69. package/lib/types/paint.d.ts +89 -4
  70. package/lib/types/plan.d.ts +7 -0
  71. package/lib/types/preset-authoring.d.ts +135 -0
  72. package/lib/types/preset-picker.d.ts +64 -0
  73. package/lib/types/preset-rows.d.ts +113 -9
  74. package/lib/types/selection.d.ts +81 -0
  75. package/lib/types/term-text.d.ts +29 -0
  76. package/lib/types/tool-present.d.ts +53 -3
  77. package/lib/types/transcript-types.d.ts +12 -2
  78. package/lib/types/tui.d.ts +231 -2
  79. package/package.json +33 -32
@@ -0,0 +1,110 @@
1
+ /**
2
+ * `/preset`: the terminal's authoring surface for agent presets.
3
+ *
4
+ * A preset is a directory — an id, a composition file, and optional display
5
+ * metadata — and the web client reaches the same four operations the plugin
6
+ * exposes to it: list, read, copy, delete. This module mirrors that surface and
7
+ * adds display-name/description edits, which are the one authoring write the
8
+ * upstream service does not offer; it stays pure so every refusal is testable
9
+ * without a host, and `tui.ts` performs the two calls that touch the disk.
10
+ *
11
+ * The rules are the upstream ones, re-stated here so a command refuses before
12
+ * it calls out:
13
+ *
14
+ * - only `user` presets are writable; a shipped preset is refused by the
15
+ * service as well (`agent-preset/read-only`);
16
+ * - a copy never overwrites: the destination id must be free;
17
+ * - ids match `/^[a-z0-9][a-z0-9-]*$/`;
18
+ * - deleting the preset the session is running is refused here, even though the
19
+ * service allows it — the running session would keep its composition while
20
+ * every later launch falls back to the default.
21
+ * @module dsh-ssh-tui/preset-authoring
22
+ */
23
+ import { dirname } from 'node:path';
24
+ import { renderPresetMetadata, } from '@deepseek-ai/dsh-agent-presets';
25
+ /** The id shape discovery accepts; a directory that fails it is skipped. */
26
+ export const PRESET_ID_PATTERN = /^[a-z0-9][a-z0-9-]*$/u;
27
+ /** Whether an id would be discovered at all. */
28
+ export function validatePresetId(id) {
29
+ return PRESET_ID_PATTERN.test(id);
30
+ }
31
+ /**
32
+ * The directory a preset owns.
33
+ *
34
+ * `AgentPreset.path` is the composition file the preset publishes, not the
35
+ * directory, so anything that writes beside it (display metadata) starts here.
36
+ * @param preset - a discovered preset.
37
+ * @returns the absolute preset directory.
38
+ */
39
+ export function presetDirectory(preset) {
40
+ return dirname(preset.path);
41
+ }
42
+ export function isRefusal(value) {
43
+ return 'error' in value;
44
+ }
45
+ /**
46
+ * Plan a copy of an existing preset under a new id.
47
+ *
48
+ * Copy is the only way to create one (upstream has no create or rename), and it
49
+ * carries the whole directory — composition, display metadata, and any scripts
50
+ * a preset ships beside them.
51
+ * @param input - the roster, whether authoring is possible, and the request.
52
+ * @returns the call to make, or why it must be refused.
53
+ */
54
+ export function planCopy(input) {
55
+ if (!input.authorable)
56
+ return { error: 'read-only' };
57
+ if (!validatePresetId(input.id))
58
+ return { error: 'invalid-id', id: input.id };
59
+ if (!input.presets.some(preset => preset.id === input.from))
60
+ return { error: 'not-found', id: input.from };
61
+ const taken = input.presets.find(preset => preset.id === input.id);
62
+ if (taken !== undefined)
63
+ return { error: 'exists', id: input.id, name: taken.name ?? taken.id };
64
+ return {
65
+ kind: 'copy',
66
+ from: input.from,
67
+ id: input.id,
68
+ ...(input.name === undefined || input.name.trim() === '' ? {} : { name: input.name.trim() }),
69
+ };
70
+ }
71
+ /**
72
+ * Plan a display-metadata edit (name, description, or both).
73
+ *
74
+ * The current document is merged, so editing one field never drops the other,
75
+ * and `order` survives. A shipped preset cannot be edited: its directory is
76
+ * read-only by definition.
77
+ * @param input - the preset, its current metadata, and the fields to change.
78
+ * @returns the file to write, or why it must be refused.
79
+ */
80
+ export function planMetadata(input) {
81
+ if (input.preset.trust !== 'user')
82
+ return { error: 'system', id: input.preset.id };
83
+ const merged = {
84
+ ...input.current,
85
+ ...(input.patch.name === undefined ? {} : { name: input.patch.name.trim() }),
86
+ ...(input.patch.description === undefined ? {} : { description: input.patch.description.trim() }),
87
+ };
88
+ const text = renderPresetMetadata(merged);
89
+ // Upstream renders nothing when every field is empty: there is no document to
90
+ // publish, and silently deleting the file is not this command's business.
91
+ if (text === undefined)
92
+ return { error: 'empty-metadata', id: input.preset.id };
93
+ return { kind: 'metadata', id: input.preset.id, directory: presetDirectory(input.preset), text };
94
+ }
95
+ /**
96
+ * Plan a deletion.
97
+ * @param input - the preset, whether authoring is possible, and which preset
98
+ * this session is running.
99
+ * @returns the call to make, or why it must be refused.
100
+ */
101
+ export function planDelete(input) {
102
+ if (!input.authorable)
103
+ return { error: 'read-only' };
104
+ if (input.preset.trust !== 'user')
105
+ return { error: 'system', id: input.preset.id };
106
+ if (input.current)
107
+ return { error: 'running', id: input.preset.id };
108
+ return { kind: 'delete', id: input.preset.id };
109
+ }
110
+ //# sourceMappingURL=preset-authoring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preset-authoring.js","sourceRoot":"","sources":["../src/preset-authoring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EACL,oBAAoB,GAGrB,MAAM,gCAAgC,CAAA;AAEvC,4EAA4E;AAC5E,MAAM,CAAC,MAAM,iBAAiB,GAAG,uBAAuB,CAAA;AAExD,gDAAgD;AAChD,MAAM,UAAU,gBAAgB,CAAC,EAAU;IACzC,OAAO,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;AACnC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,MAAmB;IACjD,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;AAC7B,CAAC;AAyCD,MAAM,UAAU,SAAS,CAAC,KAAiC;IACzD,OAAO,OAAO,IAAI,KAAK,CAAA;AACzB,CAAC;AAiCD;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,KAMxB;IACC,IAAI,CAAC,KAAK,CAAC,UAAU;QAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAA;IACpD,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,CAAA;IAC7E,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,KAAK,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,CAAA;IAC1G,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,KAAK,KAAK,CAAC,EAAE,CAAC,CAAA;IAClE,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE,EAAE,CAAA;IAC/F,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;KAC7F,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,KAI5B;IACC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,KAAK,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,CAAA;IAClF,MAAM,MAAM,GAAmB;QAC7B,GAAG,KAAK,CAAC,OAAO;QAChB,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QAC5E,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC;KAClG,CAAA;IACD,MAAM,IAAI,GAAG,oBAAoB,CAAC,MAAM,CAAC,CAAA;IACzC,8EAA8E;IAC9E,0EAA0E;IAC1E,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,CAAA;IAC/E,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,SAAS,EAAE,eAAe,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,CAAA;AAClG,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,KAI1B;IACC,IAAI,CAAC,KAAK,CAAC,UAAU;QAAE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAA;IACpD,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,KAAK,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,CAAA;IAClF,IAAI,KAAK,CAAC,OAAO;QAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,CAAA;IACnE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,CAAA;AAChD,CAAC"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * The `/mode` picker's list: which presets to show, in what order, and what to
3
+ * say about each one.
4
+ *
5
+ * The dialog is a flat list of options, so the grouping a browser surface can
6
+ * draw is carried in three cheap ways: the groups are ordered (shipped first,
7
+ * then authored locally), every description names its group, and a preset that
8
+ * declares a position shows it. Nothing here touches the filesystem or the
9
+ * service — the caller passes what `list()` returned.
10
+ * @module dsh-ssh-tui/preset-picker
11
+ */
12
+ import { t } from './i18n/index.js';
13
+ import { presetLabel } from './preset-label.js';
14
+ /**
15
+ * Within a group: a declared position first, in ascending order, then the rest
16
+ * by id. `order` is the preset's own statement about where it belongs, so a
17
+ * deployment's curated sequence survives discovery.
18
+ */
19
+ export function comparePresets(left, right) {
20
+ const leftOrder = left.order;
21
+ const rightOrder = right.order;
22
+ if (leftOrder !== undefined && rightOrder !== undefined && leftOrder !== rightOrder) {
23
+ return leftOrder - rightOrder;
24
+ }
25
+ if (leftOrder !== undefined && rightOrder === undefined)
26
+ return -1;
27
+ if (leftOrder === undefined && rightOrder !== undefined)
28
+ return 1;
29
+ return left.id.localeCompare(right.id);
30
+ }
31
+ /**
32
+ * What one preset's line says underneath its name: where it sits, what it is
33
+ * for, and why it cannot run — in that order, because a broken preset's reason
34
+ * is the only thing the reader needs.
35
+ */
36
+ export function presetOptionDescription(preset, currentId) {
37
+ const parts = [preset.trust === 'user' ? t('mode.groupUser') : t('mode.groupSystem')];
38
+ if (preset.id === currentId)
39
+ parts.push(t('mode.currentTag'));
40
+ if (preset.broken !== undefined && preset.broken !== '') {
41
+ parts.push(t('mode.brokenSuffix', { reason: preset.broken }));
42
+ }
43
+ else if (preset.description !== undefined && preset.description.trim() !== '') {
44
+ parts.push(preset.description.trim());
45
+ }
46
+ if (preset.order !== undefined)
47
+ parts.push(t('mode.orderTag', { order: preset.order }));
48
+ return parts.join(' · ');
49
+ }
50
+ /** One option's label: the name the roster publishes, never empty. */
51
+ export function presetOptionLabel(preset) {
52
+ return presetLabel(preset.id, preset.name, preset.trust);
53
+ }
54
+ /**
55
+ * Group and order the roster for the picker.
56
+ * @param presets - what the service listed.
57
+ * @param currentId - the preset in effect, marked in each description.
58
+ * @returns shipped presets first, then authored ones; empty groups are omitted.
59
+ */
60
+ export function groupPresets(presets, currentId) {
61
+ const groups = [];
62
+ for (const trust of ['system', 'user']) {
63
+ const members = presets.filter(preset => preset.trust === trust).sort(comparePresets);
64
+ if (members.length === 0)
65
+ continue;
66
+ groups.push({
67
+ trust,
68
+ title: trust === 'user' ? t('mode.groupUser') : t('mode.groupSystem'),
69
+ options: members.map(preset => ({
70
+ id: preset.id,
71
+ label: presetOptionLabel(preset),
72
+ description: presetOptionDescription(preset, currentId),
73
+ ...(preset.broken === undefined ? {} : { broken: preset.broken }),
74
+ aliases: [...new Set([
75
+ preset.id,
76
+ ...(preset.name === undefined || preset.name.trim() === '' ? [] : [preset.name.trim()]),
77
+ presetOptionLabel(preset),
78
+ ])],
79
+ })),
80
+ });
81
+ }
82
+ return groups;
83
+ }
84
+ /** The same list, flattened the way the dialog takes it. */
85
+ export function flattenGroups(groups) {
86
+ return groups.flatMap(group => group.options);
87
+ }
88
+ /** Whether a preset answers to the name a caller typed. */
89
+ export function optionMatches(option, query) {
90
+ const needle = query.trim().toLowerCase();
91
+ return needle !== '' && option.aliases.some(alias => alias.toLowerCase() === needle);
92
+ }
93
+ /**
94
+ * Narrow the roster to what a typed query matches: the id, the published name,
95
+ * and the description, case-insensitively. An empty query keeps everything, so
96
+ * the picker opens on the full roster.
97
+ */
98
+ export function filterPresets(presets, query) {
99
+ const needle = query.trim().toLowerCase();
100
+ if (needle === '')
101
+ return [...presets];
102
+ return presets.filter(preset => [preset.id, preset.name ?? '', preset.description ?? '']
103
+ .some(field => field.toLowerCase().includes(needle)));
104
+ }
105
+ //# sourceMappingURL=preset-picker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preset-picker.js","sourceRoot":"","sources":["../src/preset-picker.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  /**
2
- * The profile patch that mounts the agent-preset roster `/mode` needs.
2
+ * The profile patch that mounts the agent-preset roster `/mode` needs, plus the
3
+ * repair planner `/doctor` uses to fix a profile patch.
3
4
  *
4
5
  * A terminal profile built on `dsh-base` composes no preset roster (only the
5
6
  * Web bundle does), and this plugin's own bundle patch may not mount one: DSH
@@ -12,52 +13,158 @@
12
13
  * The roster is not cosmetic: without it `/mode` cannot switch, and the tools
13
14
  * the shipped presets own (`ask_user_question`, `present`, PTC's presentation)
14
15
  * are absent from the agent's catalog.
16
+ *
17
+ * Everything in this module is either a pure text function or a file write that
18
+ * takes a backup first: `/doctor` may repair a user's profile patch, and that
19
+ * must never lose the previous content or touch a row the user wrote.
15
20
  * @module dsh-ssh-tui/preset-rows
16
21
  */
17
- import { mkdir, readFile, writeFile } from 'node:fs/promises';
22
+ import { copyFile, mkdir, readFile, writeFile } from 'node:fs/promises';
18
23
  import { dirname, join } from 'node:path';
24
+ import yaml from 'js-yaml';
19
25
  /**
20
- * The exact profile patch block that mounts the roster and the two host
21
- * services the shipped presets need. `scripts/ensure-profile-rows.sh` carries
22
- * the same text; a test compares the two so they cannot drift.
26
+ * The rows the terminal profile has to mount itself: the roster `/mode` lists,
27
+ * the TypeScript runtime the PTC preset needs, and the host-owned subagent
28
+ * delegation setting.
23
29
  */
24
- export const ROSTER_PATCH_BLOCK = `# dsh-ssh-tui /mode: the agent-preset roster (standard / minimal / PTC /
30
+ export const ROSTER_ROWS = [
31
+ { id: 'agent-presets', name: '@deepseek-ai/dsh-agent-presets', config: ['default: standard'] },
32
+ { id: 'code-runtime', name: '@deepseek-ai/dsh-code-runtime-worker-thread' },
33
+ { id: 'subagent-model-selection-settings', name: '@deepseek-ai/dsh-tool-subagent/model-selection-settings' },
34
+ ];
35
+ /** The comment header the block introduces itself with, in both writers. */
36
+ export const ROSTER_PATCH_HEADER = `# dsh-ssh-tui /mode: the agent-preset roster (standard / minimal / PTC /
25
37
  # cordis, plus every preset under $DSH_HOME/.agent-presets) and the two host
26
38
  # services the shipped presets need. dsh-base composes no roster in a terminal
27
39
  # profile, and a third-party bundle patch may not mount an @deepseek-ai row, so
28
40
  # the profile's user layer owns them.
29
- - insert:
30
- - id: agent-presets
31
- name: '@deepseek-ai/dsh-agent-presets'
32
- config:
33
- default: standard
34
-
35
- - id: code-runtime
36
- name: '@deepseek-ai/dsh-code-runtime-worker-thread'
37
-
38
- - id: subagent-model-selection-settings
39
- name: '@deepseek-ai/dsh-tool-subagent/model-selection-settings'
40
41
  `;
42
+ /** One item of an `insert:` list, indented as the block writes it. */
43
+ function rosterItemText(row) {
44
+ const lines = [` - id: ${row.id}`, ` name: '${row.name}'`];
45
+ if (row.config !== undefined && row.config.length > 0) {
46
+ lines.push(' config:');
47
+ for (const line of row.config)
48
+ lines.push(` ${line}`);
49
+ }
50
+ return `${lines.join('\n')}\n`;
51
+ }
52
+ /** One top-level `- insert:` entry mounting exactly these rows. */
53
+ export function rosterInsertEntry(rows) {
54
+ return `- insert:\n${rows.map(rosterItemText).join('\n')}`;
55
+ }
56
+ /**
57
+ * The exact profile patch block that mounts the roster and the two host
58
+ * services the shipped presets need. `scripts/ensure-profile-rows.sh` carries
59
+ * the same text; a test compares the two so they cannot drift.
60
+ */
61
+ export const ROSTER_PATCH_BLOCK = `${ROSTER_PATCH_HEADER}${rosterInsertEntry(ROSTER_ROWS)}`;
41
62
  /** The profile patch file the roster block belongs in. */
42
63
  export function rosterPatchPath(home, profile) {
43
64
  return join(home, 'profiles', profile, 'cordis.patch.yml');
44
65
  }
66
+ /** Every `id:` the raw text writes, with the 1-based line it sits on, in order. */
67
+ function idLines(text) {
68
+ const out = [];
69
+ text.split('\n').forEach((line, index) => {
70
+ const match = /^\s*(?:-\s*)?id:\s*['"]?([^'"\s#]+)['"]?/u.exec(line);
71
+ if (match?.[1] !== undefined)
72
+ out.push({ id: match[1], line: index + 1 });
73
+ });
74
+ return out;
75
+ }
45
76
  /**
46
- * The patch text with the roster block appended, or `undefined` when the file
47
- * already names the roster row.
77
+ * Read one patch file into the rows it declares.
48
78
  *
49
- * A file that is exactly `[]` (the profile template) is replaced, so the result
50
- * stays a valid top-level patch list; anything else keeps its content and the
51
- * block is appended after a blank line.
52
- * @param existing - the patch file's current text.
53
- * @returns the new text, or `undefined` when nothing has to change.
79
+ * Unparseable YAML is reported instead of thrown: `/doctor` has to *describe*
80
+ * a broken patch, which is exactly when the loader would refuse to boot.
81
+ * @param text - the patch file's content.
82
+ * @returns the rows, and whether the text parsed at all.
54
83
  */
55
- export function rosterPatchText(existing) {
56
- if (/name:\s*'@deepseek-ai\/dsh-agent-presets'/.test(existing))
57
- return undefined;
58
- if (/^\s*\[\s*\]\s*$/m.test(existing))
59
- return existing.replace(/^\s*\[\s*\]\s*$/m, ROSTER_PATCH_BLOCK.trimEnd() + '\n');
60
- return `${existing.endsWith('\n') ? existing : `${existing}\n`}\n${ROSTER_PATCH_BLOCK}`;
84
+ export function analyzePatch(text) {
85
+ let loaded;
86
+ try {
87
+ loaded = yaml.load(text);
88
+ }
89
+ catch (error) {
90
+ return { parseable: false, error: error instanceof Error ? error.message : String(error), rows: [] };
91
+ }
92
+ const entries = Array.isArray(loaded) ? loaded : loaded === null || loaded === undefined ? [] : [loaded];
93
+ const lines = idLines(text);
94
+ const used = new Map();
95
+ const rows = [];
96
+ const lineFor = (id) => {
97
+ const seen = used.get(id) ?? 0;
98
+ used.set(id, seen + 1);
99
+ const matches = lines.filter(entry => entry.id === id);
100
+ return matches[seen]?.line ?? matches[matches.length - 1]?.line ?? 0;
101
+ };
102
+ entries.forEach((entry, entryIndex) => {
103
+ if (typeof entry !== 'object' || entry === null)
104
+ return;
105
+ const record = entry;
106
+ const insert = record.insert;
107
+ if (Array.isArray(insert)) {
108
+ insert.forEach((item, itemIndex) => {
109
+ if (typeof item !== 'object' || item === null)
110
+ return;
111
+ const row = item;
112
+ if (typeof row.id !== 'string' || row.id === '')
113
+ return;
114
+ rows.push({
115
+ id: row.id,
116
+ ...(typeof row.name === 'string' && row.name !== '' ? { name: row.name } : {}),
117
+ kind: 'insert',
118
+ entry: entryIndex,
119
+ item: itemIndex,
120
+ line: lineFor(row.id),
121
+ });
122
+ });
123
+ return;
124
+ }
125
+ if (typeof record.id !== 'string' || record.id === '')
126
+ return;
127
+ const kind = record.disable === true
128
+ ? 'disable'
129
+ : 'override' in record || 'config' in record ? 'override' : 'other';
130
+ rows.push({ id: record.id, kind, entry: entryIndex, line: lineFor(record.id) });
131
+ });
132
+ return { parseable: true, rows };
133
+ }
134
+ /**
135
+ * Insert rows that appear more than once, keeping the first occurrence.
136
+ *
137
+ * A row is duplicated when an earlier insert declares the same id, or mounts
138
+ * the same module name — the two ways a second mount reaches the loader and
139
+ * fails with "service … has been registered". Overrides and disables are never
140
+ * duplicates of an insert: they target a row instead of mounting it.
141
+ * @param rows - every row the patch declares.
142
+ * @returns the later occurrences, in file order.
143
+ */
144
+ export function duplicatePatchRows(rows) {
145
+ const seenIds = new Set();
146
+ const seenNames = new Set();
147
+ const duplicates = [];
148
+ for (const row of rows) {
149
+ if (row.kind !== 'insert')
150
+ continue;
151
+ const duplicate = seenIds.has(row.id) || (row.name !== undefined && seenNames.has(row.name));
152
+ seenIds.add(row.id);
153
+ if (row.name !== undefined)
154
+ seenNames.add(row.name);
155
+ if (duplicate)
156
+ duplicates.push(row);
157
+ }
158
+ return duplicates;
159
+ }
160
+ /** Whether a patch already declares one roster row, by id or by module name. */
161
+ export function patchNamesRow(rows, row) {
162
+ return rows.some(candidate => (candidate.kind === 'insert' && candidate.id === row.id)
163
+ || candidate.name === row.name);
164
+ }
165
+ /** The roster rows a patch does not declare yet. */
166
+ export function missingRosterRows(rows) {
167
+ return ROSTER_ROWS.filter(row => !patchNamesRow(rows, row));
61
168
  }
62
169
  /** The template a missing profile patch starts from. */
63
170
  const PATCH_TEMPLATE = `# Your patch layer for this dsh profile, applied after every bundle layer:
@@ -66,6 +173,125 @@ const PATCH_TEMPLATE = `# Your patch layer for this dsh profile, applied after e
66
173
  []
67
174
 
68
175
  `;
176
+ /** Text ending in exactly one newline. */
177
+ function normalizeEnd(text) {
178
+ return `${text.replace(/\n+$/u, '')}\n`;
179
+ }
180
+ /**
181
+ * The patch text with the given roster rows mounted, or `undefined` when the
182
+ * file already declares every one of them.
183
+ *
184
+ * A row is matched by id or by module name, so a profile that composes the
185
+ * roster through its own bundle is left alone. A file that is exactly `[]`
186
+ * (the profile template) is replaced; anything else keeps its content and gains
187
+ * a new `- insert:` entry after a blank line.
188
+ * @param existing - the patch file's current text.
189
+ * @param missing - the roster rows to mount; defaults to all of them.
190
+ * @returns the new text, or `undefined` when nothing has to change.
191
+ */
192
+ export function planRosterRepair(existing, missing = ROSTER_ROWS) {
193
+ const analysis = analyzePatch(existing);
194
+ const toAdd = analysis.parseable
195
+ ? missing.filter(row => !patchNamesRow(analysis.rows, row))
196
+ : [...missing];
197
+ if (toAdd.length === 0)
198
+ return undefined;
199
+ const entry = `${ROSTER_PATCH_HEADER}${rosterInsertEntry(toAdd)}`;
200
+ if (/^\s*\[\s*\]\s*$/m.test(existing)) {
201
+ return { text: existing.replace(/^\s*\[\s*\]\s*$/m, entry.trimEnd() + '\n'), added: toAdd.map(row => row.id), removed: [] };
202
+ }
203
+ return { text: `${normalizeEnd(existing)}\n${entry}`, added: toAdd.map(row => row.id), removed: [] };
204
+ }
205
+ /** Top-level entry ranges, each extended over directly preceding comments. */
206
+ function entryRanges(lines) {
207
+ const starts = [];
208
+ lines.forEach((line, index) => {
209
+ if (/^-\s/u.test(line) || /^-$/u.test(line))
210
+ starts.push(index);
211
+ });
212
+ return starts.map((start, at) => {
213
+ const end = starts[at + 1] ?? lines.length;
214
+ let head = start;
215
+ while (head > 0 && /^\s*#/u.test(lines[head - 1] ?? '') && !/^\s*$/u.test(lines[head - 1] ?? ''))
216
+ head -= 1;
217
+ // A comment block that also precedes an earlier entry belongs to that one.
218
+ if (at > 0 && head <= (starts[at - 1] ?? 0))
219
+ head = start;
220
+ return { start: head, end };
221
+ });
222
+ }
223
+ /** Item ranges inside one entry, each extended over directly preceding comments. */
224
+ function itemRanges(lines, entry) {
225
+ const starts = [];
226
+ for (let index = entry.start; index < entry.end; index += 1) {
227
+ if (/^\s+-\s/u.test(lines[index] ?? ''))
228
+ starts.push(index);
229
+ }
230
+ return starts.map((start, at) => ({ start, end: starts[at + 1] ?? entry.end }));
231
+ }
232
+ /**
233
+ * The patch text with every repeated insert removed, or `undefined` when the
234
+ * file has no duplicate.
235
+ *
236
+ * Only the later occurrence is cut, and only its own item when the enclosing
237
+ * `- insert:` entry mounts other rows too. Comments directly above a removed
238
+ * entry go with it; anything the user wrote around it stays.
239
+ * @param existing - the patch file's current text.
240
+ * @returns the new text and what was removed, or `undefined` when nothing is.
241
+ */
242
+ export function planDuplicateRepair(existing) {
243
+ const analysis = analyzePatch(existing);
244
+ const duplicates = duplicatePatchRows(analysis.rows);
245
+ if (duplicates.length === 0)
246
+ return undefined;
247
+ const lines = existing.split('\n');
248
+ const trailing = lines[lines.length - 1] === '' ? lines.pop() === '' : false;
249
+ const ranges = entryRanges(lines);
250
+ const cuts = [];
251
+ const duplicateKeys = new Set(duplicates.map(row => `${row.entry}:${row.item}`));
252
+ for (const duplicate of duplicates) {
253
+ const entry = ranges[duplicate.entry];
254
+ if (entry === undefined || duplicate.item === undefined)
255
+ continue;
256
+ // An entry whose every item repeats an earlier one goes as a whole; one that
257
+ // also mounts rows the user still needs loses only the repeated items.
258
+ const survivors = analysis.rows.filter(row => row.kind === 'insert' && row.entry === duplicate.entry && !duplicateKeys.has(`${row.entry}:${row.item}`));
259
+ if (survivors.length === 0) {
260
+ cuts.push(entry);
261
+ continue;
262
+ }
263
+ const item = itemRanges(lines, entry)[duplicate.item];
264
+ if (item !== undefined)
265
+ cuts.push(item);
266
+ }
267
+ if (cuts.length === 0)
268
+ return undefined;
269
+ const sorted = [...cuts].sort((left, right) => left.start - right.start);
270
+ const kept = [];
271
+ /** Indices in `kept` where a cut ended: the only places formatting may change. */
272
+ const seams = [];
273
+ let cursor = 0;
274
+ for (const cut of sorted) {
275
+ if (cut.start < cursor)
276
+ continue;
277
+ kept.push(...lines.slice(cursor, cut.start));
278
+ seams.push(kept.length);
279
+ cursor = cut.end;
280
+ }
281
+ kept.push(...lines.slice(cursor));
282
+ // A cut can leave two blank runs facing each other; fold them to one, and
283
+ // leave every other line of the user's file exactly as it was.
284
+ for (const seam of seams.reverse()) {
285
+ while (/^\s*$/u.test(kept[seam] ?? 'x') && /^\s*$/u.test(kept[seam - 1] ?? 'x'))
286
+ kept.splice(seam, 1);
287
+ }
288
+ const text = `${kept.join('\n').replace(/\n+$/u, '')}\n`;
289
+ return text === existing ? undefined : {
290
+ text: trailing ? text : text.replace(/\n$/u, ''),
291
+ added: [],
292
+ removed: duplicates.map(row => ({ id: row.id, line: row.line })),
293
+ };
294
+ }
69
295
  /**
70
296
  * Mount the roster in one profile, unless it is already composed.
71
297
  *
@@ -75,9 +301,10 @@ const PATCH_TEMPLATE = `# Your patch layer for this dsh profile, applied after e
75
301
  * half-written patch would only be seen by the next launch.
76
302
  * @param home - the harness home carrying `profiles/`.
77
303
  * @param profile - the profile to patch.
304
+ * @param missing - the rows to mount; defaults to the whole roster.
78
305
  * @returns `present` when the row already exists, else `written`.
79
306
  */
80
- export async function ensureRosterRows(home, profile) {
307
+ export async function ensureRosterRows(home, profile, missing = ROSTER_ROWS) {
81
308
  const path = rosterPatchPath(home, profile);
82
309
  let existing = PATCH_TEMPLATE;
83
310
  try {
@@ -86,11 +313,38 @@ export async function ensureRosterRows(home, profile) {
86
313
  catch {
87
314
  // Missing file: start from the template the launcher would have written.
88
315
  }
89
- const next = rosterPatchText(existing);
90
- if (next === undefined)
316
+ const repair = planRosterRepair(existing, missing);
317
+ if (repair === undefined)
91
318
  return 'present';
92
319
  await mkdir(dirname(path), { recursive: true });
93
- await writeFile(path, next, 'utf8');
320
+ await writeFile(path, repair.text, 'utf8');
94
321
  return 'written';
95
322
  }
323
+ /**
324
+ * Write a repaired patch next to a copy of the previous content.
325
+ *
326
+ * `/doctor` changes a file the user owns, so the old text is kept beside it
327
+ * before anything is replaced. A file that does not exist yet needs no backup.
328
+ * @param path - the patch file to replace.
329
+ * @param text - the new content.
330
+ * @param stamp - filename-safe timestamp for the backup, injectable for tests.
331
+ * @returns the backup path, or `undefined` when there was nothing to back up.
332
+ */
333
+ export async function writePatchWithBackup(path, text, stamp = new Date().toISOString().replace(/[:.]/gu, '-')) {
334
+ let backup;
335
+ try {
336
+ backup = `${path}.bak-${stamp}`;
337
+ await copyFile(path, backup);
338
+ }
339
+ catch {
340
+ backup = undefined;
341
+ }
342
+ await mkdir(dirname(path), { recursive: true });
343
+ await writeFile(path, text, 'utf8');
344
+ return backup;
345
+ }
346
+ /** The patch text the roster block would produce on its own, for callers that report it. */
347
+ export function rosterPatchText(existing) {
348
+ return planRosterRepair(existing)?.text;
349
+ }
96
350
  //# sourceMappingURL=preset-rows.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"preset-rows.js","sourceRoot":"","sources":["../src/preset-rows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAC7D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEzC;;;;GAIG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;CAgBjC,CAAA;AAED,0DAA0D;AAC1D,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,OAAe;IAC3D,OAAO,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,kBAAkB,CAAC,CAAA;AAC5D,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,eAAe,CAAC,QAAgB;IAC9C,IAAI,2CAA2C,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAA;IAChF,IAAI,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC,OAAO,CAAC,kBAAkB,EAAE,kBAAkB,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAA;IACvH,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,QAAQ,IAAI,KAAK,kBAAkB,EAAE,CAAA;AACzF,CAAC;AAED,wDAAwD;AACxD,MAAM,cAAc,GAAG;;;;;CAKtB,CAAA;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAY,EAAE,OAAe;IAClE,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;IAC3C,IAAI,QAAQ,GAAG,cAAc,CAAA;IAC7B,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,yEAAyE;IAC3E,CAAC;IACD,MAAM,IAAI,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAA;IACtC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,SAAS,CAAA;IACxC,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC/C,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;IACnC,OAAO,SAAS,CAAA;AAClB,CAAC"}
1
+ {"version":3,"file":"preset-rows.js","sourceRoot":"","sources":["../src/preset-rows.ts"],"names":[],"mappings":"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"}