dsh-coding-sidebar 1.0.7 → 1.0.9

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 (81) hide show
  1. package/README.md +2 -2
  2. package/lib/client-editor.js +485 -228
  3. package/lib/client-registry.js +1238 -7583
  4. package/lib/client-terminal.js +345 -189
  5. package/lib/client.js +1213 -7558
  6. package/lib/index.js +518 -69
  7. package/lib/types/agent-pty.d.ts +62 -4
  8. package/lib/types/bundle-route.d.ts +1 -1
  9. package/lib/types/client/DiffView.d.ts +33 -1
  10. package/lib/types/client/EditorHost.d.ts +4 -1
  11. package/lib/types/client/FileTree.d.ts +6 -2
  12. package/lib/types/client/TerminalWaitBanner.d.ts +6 -0
  13. package/lib/types/client/TreePanel.d.ts +4 -1
  14. package/lib/types/client/api.d.ts +26 -0
  15. package/lib/types/client/chunk-loader.d.ts +1 -1
  16. package/lib/types/client/chunks/locale.d.ts +3 -0
  17. package/lib/types/client/conversation-draft.d.ts +85 -4
  18. package/lib/types/client/locales.d.ts +13 -20
  19. package/lib/types/client/selection-popup.d.ts +58 -0
  20. package/lib/types/client/service.d.ts +1 -1
  21. package/lib/types/client/state.d.ts +15 -0
  22. package/lib/types/client/terminal-font.d.ts +25 -2
  23. package/lib/types/context-types.d.ts +3 -1
  24. package/lib/types/fs-operations.d.ts +42 -0
  25. package/lib/types/git.d.ts +15 -0
  26. package/lib/types/index.d.ts +9 -0
  27. package/lib/types/prefs-shared.d.ts +7 -5
  28. package/lib/types/pty-manager.d.ts +53 -0
  29. package/lib/types/wire.d.ts +6 -2
  30. package/package.json +1 -1
  31. package/src/agent-pty.ts +221 -33
  32. package/src/bundle-route.ts +1 -1
  33. package/src/client/DiffTab.tsx +10 -1
  34. package/src/client/DiffView.tsx +174 -19
  35. package/src/client/EditorHost.tsx +9 -2
  36. package/src/client/FileTree.tsx +151 -8
  37. package/src/client/Sidebar.tsx +95 -25
  38. package/src/client/TerminalView.tsx +41 -0
  39. package/src/client/TerminalWaitBanner.tsx +32 -0
  40. package/src/client/TextEditor.tsx +27 -45
  41. package/src/client/TreePanel.tsx +22 -2
  42. package/src/client/api.ts +20 -0
  43. package/src/client/chunk-loader.ts +1 -1
  44. package/src/client/chunks/locale.tsx +60 -0
  45. package/src/client/conversation-draft.ts +233 -7
  46. package/src/client/index.tsx +19 -8
  47. package/src/client/locales-ar.ts +17 -4
  48. package/src/client/locales-de.ts +17 -4
  49. package/src/client/locales-fr.ts +17 -4
  50. package/src/client/locales-hi.ts +17 -4
  51. package/src/client/locales-id.ts +17 -4
  52. package/src/client/locales-it.ts +17 -4
  53. package/src/client/locales-ja.ts +17 -4
  54. package/src/client/locales-ko.ts +17 -4
  55. package/src/client/locales-nl.ts +17 -4
  56. package/src/client/locales-pl.ts +17 -4
  57. package/src/client/locales-pt.ts +17 -4
  58. package/src/client/locales-ru.ts +17 -4
  59. package/src/client/locales-sv.ts +17 -4
  60. package/src/client/locales-th.ts +17 -4
  61. package/src/client/locales-tr.ts +17 -4
  62. package/src/client/locales-vi.ts +17 -4
  63. package/src/client/locales-zh-HK.ts +17 -4
  64. package/src/client/locales-zh-MO.ts +17 -4
  65. package/src/client/locales-zh-TW.ts +17 -4
  66. package/src/client/locales.ts +41 -51
  67. package/src/client/selection-popup.ts +155 -0
  68. package/src/client/service.ts +1 -1
  69. package/src/client/sidebar.module.css +68 -0
  70. package/src/client/state.ts +56 -10
  71. package/src/client/terminal-font.ts +34 -3
  72. package/src/context-types.ts +3 -2
  73. package/src/fs-operations.ts +126 -4
  74. package/src/git.ts +56 -3
  75. package/src/index.ts +82 -7
  76. package/src/open-external.ts +3 -4
  77. package/src/prefs-shared.ts +7 -5
  78. package/src/pty-manager.ts +176 -5
  79. package/src/sidechat-routes.ts +13 -1
  80. package/src/tools.ts +24 -6
  81. package/src/wire.ts +3 -0
@@ -1,29 +1,255 @@
1
1
  /**
2
- * Append text to the current session's composer draft through the
2
+ * Insert text into the current session's composer draft through the
3
3
  * conversation service — the shared path behind the explorer's @-reference
4
4
  * button and the viewer selection popup. The service is resolved lazily
5
5
  * through `ctx.get` (the inject-free read the app's own plugins use); a
6
6
  * missing service or scope degrades to a logged no-op, never a crash.
7
+ *
8
+ * File references additionally use DSH's own structured insert event
9
+ * (`slash/input-insert-reference`, see `insertFileReference`) instead of
10
+ * plain draft text: the native `@file` picker emits this event, and the
11
+ * conversation input machine mints one occurrence whose chip covers the
12
+ * whole reference. Plain text `@folder/file.ts` only ever gets DSH's
13
+ * folder-ref decoration (`@folder/`) — the file name stays undecorated — so
14
+ * plain append is the fallback, not the primary path, for files.
15
+ *
16
+ * Insert position (upstream issue #425): the draft store only exposes the
17
+ * whole string (`getSnapshot().draft` + `setDraft(text)`) — there is no
18
+ * caret API on the conversation service. The composer's `<textarea>` keeps
19
+ * its last selection even while unfocused, so the live caret is probed from
20
+ * the DOM (guarded by a value-sync check), and the text is spliced at that
21
+ * position, replacing any live selection — with whitespace-aware joins, an
22
+ * insert into the middle of a sentence keeps single-space separation like
23
+ * the append path. An unknown/stale caret falls back to appending at the
24
+ * end (the pre-fix behavior).
25
+ *
26
+ * The caret is also *restored* after the insert: committing a programmatic
27
+ * draft change resets the controlled textarea's caret (observed landing at
28
+ * the start of the value), which would make every later insert probe the
29
+ * reset position and drift the stack (A|B + C + D ended up as |DACB). The
30
+ * placement (`placeComposerCaretAfterInsert`) puts the caret right after the
31
+ * inserted text once the value commit lands — the index accounts for the
32
+ * separating space on the left, so stacked inserts stay at their running
33
+ * position (A|B + C + D → ACD|B).
7
34
  */
8
35
  import type { Context, SidebarConversation } from '../context-types.ts'
9
36
 
37
+ /** A resolved composer caret/selection in draft coordinates. */
38
+ export interface DraftCaret {
39
+ start: number
40
+ end: number
41
+ }
42
+
10
43
  /**
11
- * Append `text` to the session's composer draft (space-separated, like the
12
- * @-mentions). Returns false and logs when the conversation service or
13
- * the session scope is unavailable.
44
+ * The spliced draft plus the caret index (in that draft) right after the
45
+ * inserted textthe left-side separating space shifts the caret by one,
46
+ * which naive `start + text.length` misses (it would land before the tail).
47
+ */
48
+ interface SpliceResult {
49
+ draft: string
50
+ caretAfter: number
51
+ }
52
+
53
+ /**
54
+ * Splice `text` into `draft` at `caret` (replacing any live selection) with
55
+ * whitespace-aware joins and report the caret position right after the
56
+ * inserted text. `caret === null` (position unknown) appends at the end,
57
+ * exactly like the original behavior.
58
+ */
59
+ function spliceInsert(draft: string, text: string, caret: DraftCaret | null): SpliceResult {
60
+ if (caret === null || draft === '') {
61
+ const next = draft.trim() === '' ? text : `${draft} ${text}`
62
+ return { draft: next, caretAfter: next.length }
63
+ }
64
+ const prefix = draft.slice(0, caret.start)
65
+ const suffix = draft.slice(caret.end)
66
+ if (prefix === '' && suffix === '') return { draft: text, caretAfter: text.length }
67
+ // One separating space, but never doubled against adjacent whitespace
68
+ // (or the string edges) — mirrors how typing in the middle of a sentence
69
+ // behaves.
70
+ const left = prefix === '' || /\s$/.test(prefix) ? '' : ' '
71
+ const right = suffix === '' || /^\s/.test(suffix) ? '' : ' '
72
+ return {
73
+ draft: `${prefix}${left}${text}${right}${suffix}`,
74
+ caretAfter: prefix.length + left.length + text.length,
75
+ }
76
+ }
77
+
78
+ /**
79
+ * The spliced draft string (see {@link spliceInsert}); pure string math.
80
+ */
81
+ export function insertAtCaret(draft: string, text: string, caret: DraftCaret | null): string {
82
+ return spliceInsert(draft, text, caret).draft
83
+ }
84
+
85
+ /**
86
+ * Locate the composer `<textarea>` in the conversation column: prefer the
87
+ * `data-phase`-tagged textarea (the composer's marker), falling back to any
88
+ * textarea in the column, then to a bare data-phase textarea (older host
89
+ * layouts without the column attribute). Null in jsdom-less hosts.
90
+ */
91
+ function findComposerTextarea(): HTMLTextAreaElement | null {
92
+ if (typeof document === 'undefined') return null
93
+ const column = document.querySelector('#root [data-slot="conversation"]')
94
+ const find = (scope: ParentNode): HTMLTextAreaElement | null =>
95
+ scope.querySelector('textarea[data-phase]') ?? scope.querySelector('textarea')
96
+ return column !== null
97
+ ? find(column)
98
+ : document.querySelector<HTMLTextAreaElement>('textarea[data-phase]')
99
+ }
100
+
101
+ /**
102
+ * Resolve the composer's live caret from its DOM `<textarea>`. The draft
103
+ * store has no caret API, so the sidebar reads the composed input's selection
104
+ * directly; the value-sync check (`el.value === draft`) discards stale or
105
+ * wrong-composer reads — a caret must never be applied against a draft it
106
+ * was not measured on.
107
+ *
108
+ * Returns null when the composer is missing, disabled/read-only, out of
109
+ * sync with the store draft, or has no measurable selection (odd hosts
110
+ * report null selectionStart/End).
111
+ */
112
+ export function probeComposerCaret(draft: string): DraftCaret | null {
113
+ const el = findComposerTextarea()
114
+ if (el === null || el.disabled || el.readOnly) return null
115
+ if (el.value !== draft) return null
116
+ let start = el.selectionStart
117
+ let end = el.selectionEnd
118
+ if (typeof start !== 'number' || typeof end !== 'number') return null
119
+ if (!Number.isFinite(start) || !Number.isFinite(end)) return null
120
+ start = Math.max(0, Math.min(start, draft.length))
121
+ end = Math.max(start, Math.min(end, draft.length))
122
+ return { start, end }
123
+ }
124
+
125
+ /**
126
+ * Restore the composer caret to `caretIndex` after a programmatic
127
+ * `setDraft` commit. A controlled textarea update resets the caret (React
128
+ * commits the value asynchronously and the browser moves the caret to the
129
+ * start/end), so the placement is scheduled and retried across at most two
130
+ * animation frames (setTimeout fallback), and only applied when the textarea
131
+ * still matches `expectedDraft` — a newer edit or a different composer wins
132
+ * the race untouched. The caret is clamped into the value bounds, mirroring
133
+ * how browsers clamp type-in positions.
134
+ */
135
+ export function placeComposerCaretAfterInsert(expectedDraft: string, caretIndex: number): void {
136
+ let remaining = 2
137
+ let scheduled = false
138
+ const schedule = (fn: () => void): void => {
139
+ if (scheduled) return
140
+ scheduled = true
141
+ if (typeof requestAnimationFrame === 'function') requestAnimationFrame(fn)
142
+ else setTimeout(fn, 0)
143
+ }
144
+ const place = (): void => {
145
+ scheduled = false
146
+ if (remaining <= 0) return
147
+ remaining -= 1
148
+ const el = findComposerTextarea()
149
+ if (el === null || el.disabled || el.readOnly) return
150
+ if (el.value !== expectedDraft) {
151
+ // The commit has not landed yet (or a competing edit won) — one more
152
+ // frame before giving up.
153
+ schedule(place)
154
+ return
155
+ }
156
+ const clamped = Math.max(0, Math.min(caretIndex, el.value.length))
157
+ el.setSelectionRange(clamped, clamped)
158
+ }
159
+ schedule(place)
160
+ }
161
+
162
+ /**
163
+ * Insert `text` into the session's composer draft at the composer's live
164
+ * caret (see {@link probeComposerCaret}), falling back to appending at the
165
+ * end when the caret cannot be resolved. Returns false — and logs — when the
166
+ * conversation service or the session scope is unavailable.
14
167
  */
15
168
  export function appendToDraft(ctx: Context, sessionId: string, text: string): boolean {
16
169
  try {
17
170
  const actx = ctx.sessions.scope(sessionId)
18
- if (actx === undefined) return false
171
+ if (actx === undefined) {
172
+ console.warn('[dsh-coding-sidebar] draft insert skipped: no session scope', sessionId)
173
+ return false
174
+ }
19
175
  const conversation = ctx.get('conversation') as SidebarConversation | undefined
20
- if (conversation === undefined) return false
176
+ if (conversation === undefined) {
177
+ console.warn('[dsh-coding-sidebar] draft insert skipped: conversation service unavailable')
178
+ return false
179
+ }
21
180
  const input = conversation.input.for(actx)
22
181
  const draft = input.state.getSnapshot().draft
23
- input.setDraft(draft.trim() === '' ? text : `${draft} ${text}`)
182
+ const caret = probeComposerCaret(draft)
183
+ const { draft: next, caretAfter } = spliceInsert(draft, text, caret)
184
+ input.setDraft(next)
185
+ // Put the caret right after the inserted text once the value commit
186
+ // lands — see the module doc for why this keeps stacked inserts at the
187
+ // running position.
188
+ placeComposerCaretAfterInsert(next, caretAfter)
24
189
  return true
25
190
  } catch (error) {
26
191
  console.warn('[dsh-coding-sidebar] draft insert failed:', error)
27
192
  return false
28
193
  }
29
194
  }
195
+
196
+ /**
197
+ * The DSH `@file` spelling for one relative path, mirroring the host grammar
198
+ * (`formatFileMention` in `@deepseek-ai/dsh-file-reference`): plain when
199
+ * there is no whitespace, quoted when there is, and `undefined` when the
200
+ * path contains a control character or an embedded quote the editor grammar
201
+ * cannot represent.
202
+ */
203
+ export function fileMention(relativePath: string): { mention: string; label: string } | undefined {
204
+ const path = relativePath.replace(/[\\/]+$/, '')
205
+ // eslint-disable-next-line no-control-regex -- rejecting control characters is the point of this guard
206
+ if (/[\u0000-\u001f\u007f-\u009f"]/u.test(path)) return undefined
207
+ const mention = /\s/u.test(path) ? `@"${path}"` : `@${path}`
208
+ const at = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'))
209
+ const label = at === -1 ? path : path.slice(at + 1)
210
+ return { mention, label }
211
+ }
212
+
213
+ /**
214
+ * Insert one FILE reference as a structured chip (like DSH's own `@` picker).
215
+ * The chip displays `@<basename>` but serializes to `@<relative path>` on
216
+ * send, so the reference stays a single link from trigger to basename.
217
+ *
218
+ * Directories are NOT handled here: DSH's folder grammar wants the trailing
219
+ * slash as plain text (`@dir/`) so completion can descend, which
220
+ * `appendToDraft` already covers.
221
+ */
222
+ export function insertFileReference(ctx: Context, sessionId: string, relativePath: string): boolean {
223
+ const reference = fileMention(relativePath)
224
+ if (reference === undefined) return false
225
+ try {
226
+ const actx = ctx.sessions.scope(sessionId)
227
+ if (actx === undefined) return false
228
+ const conversation = ctx.get('conversation') as SidebarConversation | undefined
229
+ if (conversation === undefined) return false
230
+ const input = conversation.input.for(actx)
231
+ const before = input.state.getSnapshot()
232
+ if (before.draftRev === undefined) return false
233
+ // The session-scope Context's typed `emit` is keyed to DSH's closed event
234
+ // map; this internal composer event is deliberately string-loose at runtime.
235
+ ;(actx as unknown as { emit(name: string, payload: unknown): void }).emit('slash/input-insert-reference', {
236
+ reference: {
237
+ source: 'reference',
238
+ ref: reference.mention,
239
+ label: reference.label,
240
+ appearance: 'file',
241
+ clipboardText: reference.mention,
242
+ },
243
+ span: {
244
+ draftRev: before.draftRev,
245
+ start: before.draft.length,
246
+ end: before.draft.length,
247
+ },
248
+ })
249
+ const after = input.state.getSnapshot()
250
+ return after.draftRev !== before.draftRev
251
+ } catch (error) {
252
+ console.warn('[dsh-coding-sidebar] file-reference insert failed:', error)
253
+ return false
254
+ }
255
+ }
@@ -25,10 +25,8 @@ import { registerSettingsNavIcon } from './settings-nav-icon.ts'
25
25
  import { loadExternalDisable, loadPrefs } from './prefs.ts'
26
26
  import { SideCardSection } from './SideCardSection.tsx'
27
27
  import { api } from './api.ts'
28
- import { LOCALE_NS, attachLocale, attachBetterLocale, t, zh, en,
29
- ja, de, fr, pt, ko, ar, hi, id, tr, vi, th, ru, it, nl, sv, pl,
30
- zhHK, zhTW, zhMO,
31
- } from './locales.ts'
28
+ import { LOCALE_NS, attachLocale, attachBetterLocale, t, zh, en } from './locales.ts'
29
+ import { loadChunk } from './chunk-loader.ts'
32
30
  import css from './sidebar.module.css'
33
31
  import './layout.css'
34
32
 
@@ -87,7 +85,12 @@ export function apply(ctx: Context): void {
87
85
  // the ja dict once the store becomes available.
88
86
  ctx.effect(() => {
89
87
  let dispose: (() => void) | undefined
88
+ // Guards the async chunk registration below: a sync() re-run (or fiber
89
+ // disposal) that lands while the chunk is still in flight must render
90
+ // that registration moot.
91
+ let generation = 0
90
92
  const sync = (): void => {
93
+ generation += 1
91
94
  dispose?.()
92
95
  dispose = undefined
93
96
  const store = ctx.get('betterLocale') as
@@ -101,10 +104,17 @@ export function apply(ctx: Context): void {
101
104
  | undefined
102
105
  attachBetterLocale(store)
103
106
  if (store !== undefined) {
104
- dispose = store.register(LOCALE_NS, {
105
- ja, de, fr, pt, ko, ar, hi, id, tr, vi, th, ru, it, nl, sv, pl,
106
- 'zh-HK': zhHK, 'zh-TW': zhTW, 'zh-MO': zhMO,
107
- })
107
+ // The 19 override dictionaries ride the lazy `locale` chunk: until
108
+ // it lands, the store has no betterSidebar entries and t() keeps
109
+ // the zh/en chain; the store's own revision bump on register
110
+ // re-renders the chrome once the dicts arrive.
111
+ const myGeneration = generation
112
+ void loadChunk('locale')
113
+ .then(mod => {
114
+ if (myGeneration !== generation) return
115
+ dispose = store.register(LOCALE_NS, mod.localeDicts as Record<string, Record<string, string>>)
116
+ })
117
+ .catch(() => { /* the dicts stay unregistered; the zh/en chain runs */ })
108
118
  }
109
119
  }
110
120
  // Initial check (picks up the store if better-locale activated first).
@@ -113,6 +123,7 @@ export function apply(ctx: Context): void {
113
123
  // activates with a persisted override, and when the user switches).
114
124
  const unsubscribe = ctx.locale.subscribe(sync)
115
125
  return () => {
126
+ generation += 1
116
127
  unsubscribe()
117
128
  dispose?.()
118
129
  attachBetterLocale(undefined)
@@ -89,6 +89,7 @@ export const ar: Record<string, string> = {
89
89
  terminalDepsFailed: 'فشل تحميل تبعية الطرفية node-pty',
90
90
  terminalDepsHint: 'شغّل الأمر التالي في طرفية أو cmd على جهاز DSH للإصلاح، ثم أعد المحاولة (يبقى node-pty متزامناً مع إصدار نواة DSH):',
91
91
  terminalDepsProfile: ' (الملف الشخصي المكتشف: {profile})',
92
+ terminalShellNotFound: 'لم يتم العثور على الصدفة المُعدَّة: {name} — تحقق من مسار الصدفة في الإعدادات → Side card → Terminal',
92
93
  preview: 'معاينة',
93
94
  edit: 'تحرير',
94
95
  refresh: 'تحديث',
@@ -155,6 +156,18 @@ export const ar: Record<string, string> = {
155
156
  produced: 'النواتج',
156
157
  producedOpen: 'فتح في الشريط الجانبي',
157
158
  disconnected: 'انقطع اتصال الطرفية، جارٍ إعادة الاتصال…',
159
+ terminalWaitBanner: 'الوكيل ينتظر {needle}',
160
+ terminalSkipWait: 'تخطي الانتظار',
161
+ gitFoldExpand: 'إظهار {count} سطرًا من السياق',
162
+ gitFoldLoading: 'جارٍ التوسيع…',
163
+ gitFoldFailed: 'فشل التوسيع',
164
+ rename: 'إعادة تسمية',
165
+ renameInvalid: 'لا يمكن أن يكون الاسم فارغًا أو يحتوي على فواصل مسار.',
166
+ delete: 'حذف',
167
+ deleteTitle: 'حذف "{name}"؟',
168
+ deleteDescFile: 'سيتم حذف هذا الملف نهائيًا ولا يمكن التراجع.',
169
+ deleteDescDir: 'سيتم حذف هذا الدليل ومحتواه نهائيًا ولا يمكن التراجع.',
170
+ dismiss: 'إغلاق',
158
171
  exited: 'خرجت عملية الطرفية',
159
172
  noSession: 'اختر محادثة لاستخدام الشريط الجانبي',
160
173
  pluginNotLoaded: 'الإضافة غير محمّلة؛ التبويب غير متاح:',
@@ -214,10 +227,10 @@ export const ar: Record<string, string> = {
214
227
  settingsConflict: 'تغيّر الإعداد في نافذة أخرى — يُرجى إعادة المحاولة',
215
228
  binaryNoPreview: 'لا يمكن معاينة هذا النوع من الملفات',
216
229
  downloadToView: 'تنزيل للعرض',
217
- settingsSubagentTitle: 'فتح صفحة المهام تلقائياً عند ظهور وكيل فرعي',
218
- settingsSubagentDesc: 'توسيع البطاقة الجانبية وفتح صفحة المهام عند توليد المحادثة الحالية لوكيل فرعي جديد؛ أوقفها للفتح يدوياً',
219
- settingsJobsTitle: 'فتح صفحة المهام الخلفية تلقائياً عند مهمة خلفية جديدة',
220
- settingsJobsDesc: 'توسيع البطاقة الجانبية وفتح صفحة المهام الخلفية عند ظهور مهمة خلفية جديدة للمحادثة الحالية (كل مهمة جديدة تُطلق ذلكأوقفها للفتح يدوياً',
230
+ settingsSubagentTitle: 'تفعيل صفحة المهام تلقائيًا عند ظهور وكيل فرعي',
231
+ settingsSubagentDesc: 'ينشّط صفحة المهام عندما تنشئ المحادثة الحالية وكيلًا فرعيًا جديدًا؛ على الشاشات الواسعة تتوسع البطاقة الجانبية أيضًا، ولا تفرض الشاشات الضيقة الدرج بملء الشاشة؛ أوقفه للفتح يدويًا',
232
+ settingsJobsTitle: 'تفعيل صفحة المهام الخلفية تلقائيًا عند مهمة خلفية جديدة',
233
+ settingsJobsDesc: 'ينشّط صفحة المهام الخلفية كلما ظهرت مهمة خلفية جديدة للمحادثة الحالية (كل مهمة جديدة تُفعّلهعلى الشاشات الواسعة تتوسع البطاقة الجانبية أيضًا، ولا تفرض الشاشات الضيقة الدرج بملء الشاشة؛ أوقفه للفتح يدويًا',
221
234
  settingsToolsTitle: 'حقن أدوات الطرفية للنموذج',
222
235
  settingsToolsDesc: 'عند التفعيل، يمكن للنموذج إنشاء وتشغيل طرفيات الشريط الجانبي عبر أدوات terminal_* الثمانية (معطّل افتراضياً)',
223
236
  settingsFontFamilyTitle: 'عائلة خط الطرفية',
@@ -74,6 +74,7 @@ export const de: Record<string, string> = {
74
74
  terminalDepsFailed: 'Die Terminal-Abhängigkeit node-pty konnte nicht geladen werden',
75
75
  terminalDepsHint: 'Führen Sie den folgenden Befehl in einem Terminal oder in cmd auf dem DSH-System aus, um dies zu beheben, und klicken Sie dann auf „Erneut versuchen“ (node-pty bleibt mit der DSH-Core-Version synchron):',
76
76
  terminalDepsProfile: ' (erkanntes Profil: {profile})',
77
+ terminalShellNotFound: 'Konfigurierte Shell nicht gefunden: {name} — Shell-Pfad unter Einstellungen → Side card → Terminal prüfen',
77
78
  preview: 'Vorschau',
78
79
  edit: 'Bearbeiten',
79
80
  refresh: 'Aktualisieren',
@@ -140,6 +141,18 @@ export const de: Record<string, string> = {
140
141
  produced: 'Erstellt',
141
142
  producedOpen: 'In der Seitenleiste öffnen',
142
143
  disconnected: 'Terminalverbindung getrennt, Verbindung wird wiederhergestellt…',
144
+ terminalWaitBanner: 'Agent wartet auf {needle}',
145
+ terminalSkipWait: 'Warten abbrechen',
146
+ gitFoldExpand: '{count} Kontextzeilen einblenden',
147
+ gitFoldLoading: 'Wird eingeblendet…',
148
+ gitFoldFailed: 'Einblenden fehlgeschlagen',
149
+ rename: 'Umbenennen',
150
+ renameInvalid: 'Der Name darf nicht leer sein und keine Pfadtrenner enthalten.',
151
+ delete: 'Löschen',
152
+ deleteTitle: '„{name}“ löschen?',
153
+ deleteDescFile: 'Diese Datei wird endgültig gelöscht. Dies kann nicht rückgängig gemacht werden.',
154
+ deleteDescDir: 'Dieses Verzeichnis und sein gesamter Inhalt werden endgültig gelöscht. Dies kann nicht rückgängig gemacht werden.',
155
+ dismiss: 'Schließen',
143
156
  exited: 'Terminalprozess beendet',
144
157
  noSession: 'Wählen Sie eine Sitzung, um die Seitenleiste zu verwenden',
145
158
  pluginNotLoaded: 'Plugin nicht geladen; Tab vorübergehend nicht verfügbar:',
@@ -199,10 +212,10 @@ export const de: Record<string, string> = {
199
212
  settingsConflict: 'Die Einstellung wurde in einem anderen Fenster geändert – bitte erneut versuchen',
200
213
  binaryNoPreview: 'Dieser Dateityp kann nicht in der Vorschau angezeigt werden',
201
214
  downloadToView: 'Zum Ansehen herunterladen',
202
- settingsSubagentTitle: 'Aufgaben-Seite bei einem Subagenten automatisch öffnen',
203
- settingsSubagentDesc: 'Die Seitenkarte wird ausgeklappt und die Aufgaben-Seite geöffnet, wenn die aktuelle Unterhaltung einen neuen Subagenten erzeugt; ausschalten, um sie manuell zu öffnen',
204
- settingsJobsTitle: 'Aufgaben-Seite bei einer neuen Hintergrundaufgabe automatisch öffnen',
205
- settingsJobsDesc: 'Die Seitenkarte wird ausgeklappt und die Aufgaben-Seite geöffnet, sobald für die aktuelle Unterhaltung eine neue Hintergrundaufgabe erscheint (jede neue Aufgabe löst dies aus); ausschalten, um sie manuell zu öffnen',
215
+ settingsSubagentTitle: 'Aufgabenseite bei neuen Subagenten automatisch aktivieren',
216
+ settingsSubagentDesc: 'Aktiviert die Aufgabenseite, wenn die aktuelle Konversation einen neuen Subagenten erzeugt; auf breiten Bildschirmen wird die Seitenkarte mit ausgeklappt, schmale Bildschirme erzwingen keine Vollbild-Schublade; zum manuellen Öffnen deaktivieren',
217
+ settingsJobsTitle: 'Aufgabenseite bei neuem Hintergrundjob automatisch aktivieren',
218
+ settingsJobsDesc: 'Aktiviert die Aufgabenseite, wenn ein neuer Hintergrundjob für die aktuelle Konversation erscheint (jeder neue Job löst aus); auf breiten Bildschirmen wird die Seitenkarte mit ausgeklappt, schmale Bildschirme erzwingen keine Vollbild-Schublade; zum manuellen Öffnen deaktivieren',
206
219
  settingsToolsTitle: 'Terminal-Werkzeuge für das Modell bereitstellen',
207
220
  settingsToolsDesc: 'Wenn aktiviert, kann das Modell über die 8 terminal_*-Werkzeuge Terminale in der Seitenleiste erstellen und steuern (standardmäßig deaktiviert)',
208
221
  settingsFontFamilyTitle: 'Terminal-Schriftart',
@@ -81,6 +81,7 @@ export const fr: Record<string, string> = {
81
81
  terminalDepsFailed: 'Échec du chargement de la dépendance terminal node-pty',
82
82
  terminalDepsHint: 'Exécutez la commande suivante dans un terminal ou cmd de l’environnement DSH pour réparer, puis cliquez sur Réessayer (node-pty reste à la même version que le cœur DSH) :',
83
83
  terminalDepsProfile: ' (profil détecté : {profile})',
84
+ terminalShellNotFound: 'Shell configuré introuvable : {name} — vérifiez le chemin du shell dans Réglages → Side card → Terminal',
84
85
  preview: 'Aperçu',
85
86
  edit: 'Modifier',
86
87
  refresh: 'Actualiser',
@@ -147,6 +148,18 @@ export const fr: Record<string, string> = {
147
148
  produced: 'Produits de cette exécution',
148
149
  producedOpen: 'Ouvrir dans la barre latérale',
149
150
  disconnected: 'Connexion du terminal perdue, reconnexion…',
151
+ terminalWaitBanner: 'L’agent attend {needle}',
152
+ terminalSkipWait: 'Ignorer l’attente',
153
+ gitFoldExpand: 'Afficher les {count} lignes de contexte',
154
+ gitFoldLoading: 'Déploiement…',
155
+ gitFoldFailed: 'Impossible de déployer',
156
+ rename: 'Renommer',
157
+ renameInvalid: 'Le nom ne peut pas être vide ni contenir de séparateur de chemin.',
158
+ delete: 'Supprimer',
159
+ deleteTitle: 'Supprimer « {name} » ?',
160
+ deleteDescFile: 'Ce fichier sera définitivement supprimé. Action irréversible.',
161
+ deleteDescDir: 'Ce répertoire et tout son contenu seront définitivement supprimés. Action irréversible.',
162
+ dismiss: 'Fermer',
150
163
  exited: 'Le processus du terminal s’est terminé',
151
164
  noSession: 'Sélectionnez une session pour utiliser la barre latérale',
152
165
  pluginNotLoaded: 'Plugin non chargé, onglet indisponible pour le moment :',
@@ -206,10 +219,10 @@ export const fr: Record<string, string> = {
206
219
  settingsConflict: 'Les réglages ont été modifiés par une autre fenêtre, veuillez réessayer',
207
220
  binaryNoPreview: 'Ce type de fichier ne prend pas en charge l’aperçu',
208
221
  downloadToView: 'Télécharger pour consulter',
209
- settingsSubagentTitle: 'Déployer automatiquement la page de gestion des tâches à la détection d’un sous-agent',
210
- settingsSubagentDesc: 'Lorsque la session actuelle produit un nouveau sous-agent, déployer automatiquement la barre latérale et ouvrir la page de gestion des tâches ; une fois désactivé, l’ouverture est manuelle',
211
- settingsJobsTitle: 'Déployer automatiquement la page des tâches d’arrière-plan sur nouvelle tâche',
212
- settingsJobsDesc: 'Lorsque la session actuelle produit une nouvelle tâche d’arrière-plan, déployer automatiquement la barre latérale et ouvrir la page des tâches (déclenché à chaque nouvelle tâche) ; une fois désactivé, l’ouverture est manuelle',
222
+ settingsSubagentTitle: 'Activer automatiquement la page des tâches quand un sous-agent apparaît',
223
+ settingsSubagentDesc: 'Active la page des tâches quand la conversation actuelle crée un nouveau sous-agent ; sur les grands écrans la carte latérale se déploie aussi, les petits écrans ne forcent jamais le tiroir plein écran ; désactivez pour ouvrir manuellement',
224
+ settingsJobsTitle: 'Activer automatiquement la page des tâches d’arrière-plan pour une nouvelle tâche',
225
+ settingsJobsDesc: 'Active la page des tâches d’arrière-plan dès qu’une nouvelle tâche apparaît pour la conversation actuelle (chaque nouvelle tâche déclenche) ; sur les grands écrans la carte latérale se déploie aussi, les petits écrans ne forcent jamais le tiroir plein écran ; désactivez pour ouvrir manuellement',
213
226
  settingsToolsTitle: 'Injecter des outils de terminal au modèle',
214
227
  settingsToolsDesc: 'Une fois activé, le modèle peut créer et piloter des terminaux de la barre latérale via les 8 outils terminal_* (désactivé par défaut)',
215
228
  settingsFontFamilyTitle: 'Police du terminal',
@@ -88,6 +88,7 @@ export const hi: Record<string, string> = {
88
88
  terminalDepsFailed: 'टर्मिनल निर्भरता node-pty लोड विफल',
89
89
  terminalDepsHint: 'DSH मशीन पर एक टर्मिनल या cmd में नीचे दिया गया कमांड चलाएँ, फिर पुनः प्रयास करें (node-pty DSH कोर संस्करण के साथ सिंक रहता है):',
90
90
  terminalDepsProfile: ' (पहचाना गया प्रोफ़ाइल: {profile})',
91
+ terminalShellNotFound: 'कॉन्फ़िगर किया गया shell नहीं मिला: {name} — Settings → Side card → Terminal में shell पथ जाँचें',
91
92
  preview: 'पूर्वावलोकन',
92
93
  edit: 'संपादित करें',
93
94
  refresh: 'ताज़ा करें',
@@ -154,6 +155,18 @@ export const hi: Record<string, string> = {
154
155
  produced: 'उत्पादित',
155
156
  producedOpen: 'साइडबार में खोलें',
156
157
  disconnected: 'टर्मिनल डिस्कनेक्ट हो गया, पुनः कनेक्ट हो रहा…',
158
+ terminalWaitBanner: 'एजेंट {needle} की प्रतीक्षा कर रहा है',
159
+ terminalSkipWait: 'प्रतीक्षा छोड़ें',
160
+ gitFoldExpand: '{count} संदर्भ पंक्तियाँ दिखाएँ',
161
+ gitFoldLoading: 'खोल रहे हैं…',
162
+ gitFoldFailed: 'खोलने में विफल',
163
+ rename: 'नाम बदलें',
164
+ renameInvalid: 'नाम खाली नहीं हो सकता या पाथ सेपरेटर नहीं हो सकता।',
165
+ delete: 'हटाएँ',
166
+ deleteTitle: '"{name}" हटाएँ?',
167
+ deleteDescFile: 'यह फ़ाइल स्थायी रूप से हट जाएगी। इसे वापस नहीं किया जा सकता।',
168
+ deleteDescDir: 'यह निर्देशिका और उसकी सामग्री स्थायी रूप से हट जाएगी। इसे वापस नहीं किया जा सकता।',
169
+ dismiss: 'बंद करें',
157
170
  exited: 'टर्मिनल प्रक्रिया बाहर निकली',
158
171
  noSession: 'साइडबार उपयोग करने के लिए एक वार्तालाप चुनें',
159
172
  pluginNotLoaded: 'प्लगइन लोड नहीं; टैब अनुपलब्ध:',
@@ -213,10 +226,10 @@ export const hi: Record<string, string> = {
213
226
  settingsConflict: 'सेटिंग दूसरी विंडो में बदली — कृपया पुनः प्रयास करें',
214
227
  binaryNoPreview: 'इस फ़ाइल प्रकार का पूर्वावलोकन नहीं हो सकता',
215
228
  downloadToView: 'देखने के लिए डाउनलोड करें',
216
- settingsSubagentTitle: 'सबएजेंट दिखने पर स्वतः कार्य पृष्ठ खोलें',
217
- settingsSubagentDesc: 'वर्तमान वार्तालाप में नया सबएजेंट बनने पर साइडबार विस्तृत करें और कार्य पृष्ठ खोलें; बंद करने पर मैन्युअल रूप से खोलें',
218
- settingsJobsTitle: 'नया बैकग्राउंड कार्य आने पर स्वतः कार्य पृष्ठ खोलें',
219
- settingsJobsDesc: 'वर्तमान वार्तालाप में नया बैकग्राउंड कार्य दिखने पर साइडबार विस्तृत करें और कार्य पृष्ठ खोलें (हर नया कार्य ट्रिगर करता है); बंद करने पर मैन्युअल रूप से खोलें',
229
+ settingsSubagentTitle: 'सब-एजेंट दिखने पर कार्य पृष्ठ स्वतः सक्रिय करें',
230
+ settingsSubagentDesc: 'जब मौजूदा बातचीत नया सब-एजेंट बनाती है तो कार्य पृष्ठ सक्रिय होता है; चौड़ी स्क्रीन पर साइड कार्ड भी खुलता है, संकरी स्क्रीन फुल-स्क्रीन ड्रॉअर बाध्य नहीं करती; मैन्युअल रूप से खोलने के लिए बंद करें',
231
+ settingsJobsTitle: 'नए बैकग्राउंड कार्य पर बैकग्राउंड कार्य पृष्ठ स्वतः सक्रिय करें',
232
+ settingsJobsDesc: 'जब मौजूदा बातचीत के लिए कोई नया बैकग्राउंड कार्य दिखे तो बैकग्राउंड कार्य पृष्ठ सक्रिय होता है (हर नया कार्य ट्रिगर करता है); चौड़ी स्क्रीन पर साइड कार्ड भी खुलता है, संकरी स्क्रीन फुल-स्क्रीन ड्रॉअर बाध्य नहीं करती; मैन्युअल रूप से खोलने के लिए बंद करें',
220
233
  settingsToolsTitle: 'मॉडल के लिए टर्मिनल टूल इंजेक्ट करें',
221
234
  settingsToolsDesc: 'सक्षम होने पर, मॉडल 8 terminal_* टूल्स से साइडबार टर्मिनल बना और चला सकता है (डिफ़ॉल्ट रूप से बंद)',
222
235
  settingsFontFamilyTitle: 'टर्मिनल फ़ॉन्ट परिवार',
@@ -86,6 +86,7 @@ export const id: Record<string, string> = {
86
86
  terminalDepsFailed: 'Dependensi terminal node-pty gagal dimuat',
87
87
  terminalDepsHint: 'Jalankan perintah di bawah ini di terminal atau cmd pada mesin DSH untuk memperbaikinya, lalu coba lagi (node-pty tetap sinkron dengan versi inti DSH):',
88
88
  terminalDepsProfile: ' (profil terdeteksi: {profile})',
89
+ terminalShellNotFound: 'Shell yang dikonfigurasi tidak ditemukan: {name} — periksa path shell di Pengaturan → Side card → Terminal',
89
90
  preview: 'Pratinjau',
90
91
  edit: 'Edit',
91
92
  refresh: 'Segarkan',
@@ -152,6 +153,18 @@ export const id: Record<string, string> = {
152
153
  produced: 'Dihasilkan',
153
154
  producedOpen: 'Buka di sidebar',
154
155
  disconnected: 'Terminal terputus, menyambung ulang…',
156
+ terminalWaitBanner: 'Agen menunggu {needle}',
157
+ terminalSkipWait: 'Lewati penungguan',
158
+ gitFoldExpand: 'Tampilkan {count} baris konteks',
159
+ gitFoldLoading: 'Membentang…',
160
+ gitFoldFailed: 'Gagal membentang',
161
+ rename: 'Ganti nama',
162
+ renameInvalid: 'Nama tidak boleh kosong atau mengandung pemisah jalur.',
163
+ delete: 'Hapus',
164
+ deleteTitle: 'Hapus "{name}"?',
165
+ deleteDescFile: 'File ini dihapus permanen dan tidak dapat dibatalkan.',
166
+ deleteDescDir: 'Direktori ini dan seluruh isinya dihapus permanen dan tidak dapat dibatalkan.',
167
+ dismiss: 'Tutup',
155
168
  exited: 'Proses terminal keluar',
156
169
  noSession: 'Pilih obrolan untuk menggunakan sidebar',
157
170
  pluginNotLoaded: 'Plugin tidak dimuat; tab tidak tersedia untuk sementara:',
@@ -211,10 +224,10 @@ export const id: Record<string, string> = {
211
224
  settingsConflict: 'Pengaturan diubah di jendela lain — silakan coba lagi',
212
225
  binaryNoPreview: 'Tipe berkas ini tidak dapat dipratinjau',
213
226
  downloadToView: 'Unduh untuk melihat',
214
- settingsSubagentTitle: 'Buka otomatis halaman Tasks saat subagen muncul',
215
- settingsSubagentDesc: 'Bentangkan kartu samping dan buka halaman Tasks saat obrolan saat ini menelurkan subagen baru; matikan untuk membukanya secara manual',
216
- settingsJobsTitle: 'Buka otomatis halaman Jobs saat ada tugas latar baru',
217
- settingsJobsDesc: 'Bentangkan kartu samping dan buka halaman Jobs setiap kali tugas latar baru muncul untuk obrolan saat ini (setiap tugas baru memicu); matikan untuk membukanya secara manual',
227
+ settingsSubagentTitle: 'Aktifkan halaman tugas secara otomatis saat ada subagen',
228
+ settingsSubagentDesc: 'Mengaktifkan halaman tugas saat percakapan saat ini membuat subagen baru; di layar lebar kartu samping juga terbuka, layar sempit tidak memaksa laci layar penuh; matikan untuk membuka manual',
229
+ settingsJobsTitle: 'Aktifkan halaman tugas latar secara otomatis saat ada tugas latar baru',
230
+ settingsJobsDesc: 'Mengaktifkan halaman tugas latar setiap kali tugas latar baru muncul untuk percakapan saat ini (setiap tugas baru memicu); di layar lebar kartu samping juga terbuka, layar sempit tidak memaksa laci layar penuh; matikan untuk membuka manual',
218
231
  settingsToolsTitle: 'Suntik alat terminal untuk model',
219
232
  settingsToolsDesc: 'Saat diaktifkan, model dapat membuat dan mengendalikan terminal sidebar melalui 8 alat terminal_* (nonaktif secara default)',
220
233
  settingsFontFamilyTitle: 'Keluarga font terminal',
@@ -79,6 +79,7 @@ export const it: Record<string, string> = {
79
79
  terminalDepsFailed: 'Caricamento della dipendenza del terminale node-pty non riuscito',
80
80
  terminalDepsHint: 'Esegua il comando seguente in un terminale o cmd sul computer DSH per ripristinarlo, poi riprovi (node-pty resta sincronizzato con la versione del core DSH):',
81
81
  terminalDepsProfile: ' (rilevato profilo: {profile})',
82
+ terminalShellNotFound: 'Shell configurata non trovata: {name} — verifica il percorso della shell in Impostazioni → Side card → Terminal',
82
83
  preview: 'Anteprima',
83
84
  edit: 'Modifica',
84
85
  refresh: 'Aggiorna',
@@ -145,6 +146,18 @@ export const it: Record<string, string> = {
145
146
  produced: 'Prodotti',
146
147
  producedOpen: 'Apri nella barra laterale',
147
148
  disconnected: 'Terminale disconnesso, riconnessione…',
149
+ terminalWaitBanner: 'L’agente sta attendendo {needle}',
150
+ terminalSkipWait: 'Salta attesa',
151
+ gitFoldExpand: 'Mostra le {count} righe di contesto',
152
+ gitFoldLoading: 'Espansione…',
153
+ gitFoldFailed: 'Impossibile espandere',
154
+ rename: 'Rinomina',
155
+ renameInvalid: 'Il nome non può essere vuoto né contenere separatori di percorso.',
156
+ delete: 'Elimina',
157
+ deleteTitle: 'Eliminare "{name}"?',
158
+ deleteDescFile: 'Il file verrà eliminato definitivamente. Operazione irreversibile.',
159
+ deleteDescDir: 'La directory e tutto il suo contenuto verranno eliminati definitivamente. Operazione irreversibile.',
160
+ dismiss: 'Chiudi',
148
161
  exited: 'Il processo del terminale è terminato',
149
162
  noSession: 'Selezioni una conversazione per usare la barra laterale',
150
163
  pluginNotLoaded: 'Plugin non caricato; scheda non disponibile:',
@@ -204,10 +217,10 @@ export const it: Record<string, string> = {
204
217
  settingsConflict: 'L’impostazione è stata modificata in un’altra finestra — riprovi',
205
218
  binaryNoPreview: 'Questo tipo di file non può essere visualizzato in anteprima',
206
219
  downloadToView: 'Scarica per visualizzare',
207
- settingsSubagentTitle: 'Apri automaticamente la pagina Attività quando compare un sottoagente',
208
- settingsSubagentDesc: 'Espande la barra laterale e apre la pagina Attività quando la conversazione attuale genera un nuovo sottoagente; disattivato va aperta manualmente',
209
- settingsJobsTitle: 'Apri automaticamente la pagina Attività in background in caso di nuova attività',
210
- settingsJobsDesc: 'Espande la barra laterale e apre la pagina Attività in background ogni volta che compare una nuova attività in background per la conversazione attuale (ogni nuova attività la attiva); disattivato va aperta manualmente',
220
+ settingsSubagentTitle: 'Attiva automaticamente la pagina attività quando compare un sottoagente',
221
+ settingsSubagentDesc: 'Attiva la pagina attività quando la conversazione corrente genera un nuovo sottoagente; sugli schermi larghi si espande anche la scheda laterale, quelli stretti non forzano il cassetto a schermo intero; disattiva per aprire manualmente',
222
+ settingsJobsTitle: 'Attiva automaticamente la pagina attività in background per una nuova attività',
223
+ settingsJobsDesc: 'Attiva la pagina attività in background ogni volta che compare una nuova attività per la conversazione corrente (ogni nuova attività la attiva); sugli schermi larghi si espande anche la scheda laterale, quelli stretti non forzano il cassetto a schermo intero; disattiva per aprire manualmente',
211
224
  settingsToolsTitle: 'Inietta strumenti del terminale per il modello',
212
225
  settingsToolsDesc: 'Se attivato, il modello può creare e gestire terminali della barra laterale attraverso gli 8 strumenti terminal_* (disattivato per impostazione predefinita)',
213
226
  settingsFontFamilyTitle: 'Famiglia di caratteri del terminale',
@@ -88,6 +88,7 @@ export const ja: Record<string, string> = {
88
88
  terminalDepsFailed: 'ターミナル依存関係 node-pty の読み込みに失敗',
89
89
  terminalDepsHint: 'DSH 環境のターミナルまたは cmd で以下のコマンドを実行して修復し、再試行してください(node-pty は DSH コアと同じバージョンを維持):',
90
90
  terminalDepsProfile: '(検出された profile:{profile})',
91
+ terminalShellNotFound: '設定されたシェルが見つかりません:{name}(設定 → サイドカード → ターミナル のシェルパスを確認してください)',
91
92
  preview: 'プレビュー',
92
93
  edit: '編集',
93
94
  refresh: '更新',
@@ -154,6 +155,18 @@ export const ja: Record<string, string> = {
154
155
  produced: '今回の産物',
155
156
  producedOpen: 'サイドバーで開く',
156
157
  disconnected: 'ターミナル接続が切れました、再接続中…',
158
+ terminalWaitBanner: 'エージェントが {needle} を待機中',
159
+ terminalSkipWait: '待機をスキップ',
160
+ gitFoldExpand: 'コンテキスト {count} 行を表示',
161
+ gitFoldLoading: '展開中…',
162
+ gitFoldFailed: '展開できませんでした',
163
+ rename: '名前を変更',
164
+ renameInvalid: '名前は空にできないか、パス区切りを含めてはいけません。',
165
+ delete: '削除',
166
+ deleteTitle: '「{name}」を削除しますか?',
167
+ deleteDescFile: 'このファイルは完全に削除されます。元に戻せません。',
168
+ deleteDescDir: 'このディレクトリとその内容は完全に削除されます。元に戻せません。',
169
+ dismiss: '閉じる',
157
170
  exited: 'ターミナルプロセスが終了しました',
158
171
  noSession: 'サイドバーを使うには会話を選択してください',
159
172
  pluginNotLoaded: 'プラグイン未読み込み、タブは一時的に利用不可:',
@@ -213,10 +226,10 @@ export const ja: Record<string, string> = {
213
226
  settingsConflict: '設定が別のウィンドウで変更されました、再試行してください',
214
227
  binaryNoPreview: 'このファイル形式はプレビューできません',
215
228
  downloadToView: 'ダウンロードして表示',
216
- settingsSubagentTitle: 'サブエージェント検出時に自動展開',
217
- settingsSubagentDesc: '現在の会話で新しいサブエージェントが発生した際、サイドバーを自動展開してタスク管理ページを開く。オフ時は手動で開く必要あり',
218
- settingsJobsTitle: '新規バックグラウンドタスク時に自動展開',
219
- settingsJobsDesc: '現在の会話で新しいバックグラウンドタスクが発生するたびにサイドバーを展開してタスクページを開く(新規タスクごとに発火)。オフ時は手動で開く必要あり',
229
+ settingsSubagentTitle: 'サブエージェント検出時にタスク管理ページを自動アクティブ化',
230
+ settingsSubagentDesc: '現在のセッションで新しいサブエージェントが生成されると、タスク管理ページを自動アクティブ化します。幅の広い画面ではサイドカードも展開し、狭い画面では全画面ドロワーを強制しません。オフにすると手動で開きます',
231
+ settingsJobsTitle: '新しいバックグラウンドタスク時にタスクページを自動アクティブ化',
232
+ settingsJobsDesc: '現在のセッションに新しいバックグラウンドタスクが現れると、バックグラウンドタスクページを自動アクティブ化します(すべての新タスクで発火)。幅の広い画面ではサイドカードも展開し、狭い画面では全画面ドロワーを強制しません。オフにすると手動で開きます',
220
233
  settingsToolsTitle: 'モデルにターミナルツールを注入',
221
234
  settingsToolsDesc: 'オンにすると、モデルが terminal_create 等 8 個のツールでサイドバーターミナルを作成・操作可能(デフォルトオフ)',
222
235
  settingsFontFamilyTitle: 'ターミナルフォント',