dsh-grove 0.5.0 → 0.5.1

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 (2) hide show
  1. package/client.js +39 -53
  2. package/package.json +2 -1
package/client.js CHANGED
@@ -33,6 +33,8 @@ window.__ModuleLoader__.load({
33
33
  var INSPIRATIONS = '/api/grove/inspirations'
34
34
 
35
35
  var ZH = {
36
+ 's0.pickerUnavailable': '这个宿主暂时无法打开文件夹选择器。可以手动输入路径。',
37
+ 's0.pickerFailed': '没能打开文件夹选择器。{message}',
36
38
  'asset.knowledge': '知识库',
37
39
  'asset.works': '作品',
38
40
  'asset.title': '标题',
@@ -98,24 +100,19 @@ window.__ModuleLoader__.load({
98
100
  'idea.version': '历史版本',
99
101
  panel: 'Grove',
100
102
  menu: '知林',
101
- subtitle: '把探索留在自己的 vault 里。',
103
+ subtitle: '记灵感,做研究',
102
104
  'status.connected': '已连接',
103
105
  'status.disconnected': '未连接',
104
106
  'status.readonly': '只读',
105
107
  'status.checking': '正在读取…',
106
- 's0.title': '先连接你的 Obsidian vault',
107
- 's0.body': 'Grove 只读写 vault 里的 Grove/ 文件夹,不读其他笔记。连接后,Harness 里的对话就能落成可回看、可修订的 Markdown。',
108
- 's0.step1': '连接 vault',
109
- 's0.step2': '写下第一条灵感',
110
- 's0.step3': '回到会话继续探索',
108
+ 's0.title': '连接 Obsidian 笔记库',
109
+ 's0.body': '选一下你在 Obsidian 里打开的笔记库文件夹,连好就能记下第一个灵感。',
111
110
  's0.pick': '选择文件夹',
112
111
  's0.manual': '手动输入路径',
113
112
  's0.placeholder': '/Users/你/Obsidian Vault',
114
113
  's0.connect': '连接',
115
114
  's0.cancel': '取消',
116
- 's0.hint': '路径会保存到当前 profile 的插件配置;之后可在插件页里修改。',
117
115
  's0.stale': '原来的 vault 已不可用:{path}。请重新选择,或把它移回原位。',
118
- 's0.noVault': '这个文件夹里没有 .obsidian。如果它不是 vault 根目录,仍可继续连接。',
119
116
  's1.change': '更换 vault',
120
117
  'type.inspiration': '灵感',
121
118
  'type.question': '问题',
@@ -127,9 +124,7 @@ window.__ModuleLoader__.load({
127
124
  'type.output': '成果',
128
125
  'type.exploration': '探索',
129
126
  'type.research': '研究',
130
- 'foot.privacy': 'Grove 只读写 vault 的 Grove/ 文件夹,不读其他笔记。',
131
- 'foot.confirm': 'AI 起草的草稿要你在终端确认后才落盘。',
132
- 'foot.data': '数据是你的 Markdown,随时可以备份或迁移。',
127
+ 'foot.privacy': '灵感和研究保存在笔记库的 Grove/ 文件夹里。',
133
128
  'err.invalid-path': '路径无效,请填写绝对路径。',
134
129
  'err.not-directory': '这个路径不是文件夹。',
135
130
  'err.symlink': '这个路径是符号链接,请选择真实目录。',
@@ -146,6 +141,8 @@ window.__ModuleLoader__.load({
146
141
  }
147
142
 
148
143
  var EN = {
144
+ 's0.pickerUnavailable': 'This host cannot open a folder picker. You can enter the path manually.',
145
+ 's0.pickerFailed': 'Could not open the folder picker. {message}',
149
146
  'asset.knowledge': 'Knowledge',
150
147
  'asset.works': 'Works',
151
148
  'asset.title': 'Title',
@@ -211,24 +208,19 @@ window.__ModuleLoader__.load({
211
208
  'idea.version': 'History',
212
209
  panel: 'Grove',
213
210
  menu: 'Grove',
214
- subtitle: 'Keep what you explore in your own vault.',
211
+ subtitle: 'Capture ideas and do research',
215
212
  'status.connected': 'Connected',
216
213
  'status.disconnected': 'Not connected',
217
214
  'status.readonly': 'Read only',
218
215
  'status.checking': 'Reading…',
219
216
  's0.title': 'Connect your Obsidian vault',
220
- 's0.body': 'Grove reads and writes only the Grove/ folder inside your vault, never other notes. Once connected, conversations in Harness can become Markdown you can revisit and revise.',
221
- 's0.step1': 'Connect a vault',
222
- 's0.step2': 'Capture a first idea',
223
- 's0.step3': 'Go back to the conversation',
217
+ 's0.body': 'Choose the folder you open as a vault in Obsidian. Once it’s connected, you can jot down your first idea.',
224
218
  's0.pick': 'Choose folder',
225
219
  's0.manual': 'Enter a path',
226
220
  's0.placeholder': '/Users/you/Obsidian Vault',
227
221
  's0.connect': 'Connect',
228
222
  's0.cancel': 'Cancel',
229
- 's0.hint': 'The path is saved in this profile’s plugin configuration and can be changed later from the Plugins page.',
230
223
  's0.stale': 'The previous vault is no longer usable: {path}. Choose it again, or move it back.',
231
- 's0.noVault': 'This folder has no .obsidian. You can still connect if it is a vault root.',
232
224
  's1.change': 'Change vault',
233
225
  'type.inspiration': 'Inspiration',
234
226
  'type.question': 'Question',
@@ -240,9 +232,7 @@ window.__ModuleLoader__.load({
240
232
  'type.output': 'Output',
241
233
  'type.exploration': 'Exploration',
242
234
  'type.research': 'Research',
243
- 'foot.privacy': 'Grove reads and writes only the vault’s Grove/ folder, never other notes.',
244
- 'foot.confirm': 'Content drafted by AI is saved only after you confirm it in the terminal.',
245
- 'foot.data': 'Your data is Markdown you can back up or move at any time.',
235
+ 'foot.privacy': 'Your ideas and research are saved in the Grove/ folder inside your vault.',
246
236
  'err.invalid-path': 'That path is not valid. Use an absolute path.',
247
237
  'err.not-directory': 'That path is not a folder.',
248
238
  'err.symlink': 'That path is a symlink. Choose a real directory.',
@@ -259,7 +249,7 @@ window.__ModuleLoader__.load({
259
249
  }
260
250
 
261
251
  var boundT = null
262
- var services = { workspace: null }
252
+ var services = { picker: null }
263
253
 
264
254
  function T(key, vars) {
265
255
  if (boundT) {
@@ -383,25 +373,26 @@ window.__ModuleLoader__.load({
383
373
  })
384
374
  }
385
375
 
386
- function pickFolder() {
387
- var workspace = services.workspace
388
- if (!workspace || typeof workspace.pickDirectory !== 'function') {
389
- setManual(true)
376
+ async function pickFolder() {
377
+ if (busy) return
378
+ var picker = services.picker
379
+ if (!picker) {
380
+ setError(new Error(T('s0.pickerUnavailable')))
390
381
  return
391
382
  }
383
+ setError(null)
392
384
  setBusy('pick')
393
- Promise.resolve(workspace.pickDirectory()).then(function (path) {
394
- if (!path) {
395
- if (mounted.current) setBusy('')
396
- return
397
- }
385
+ var path
386
+ try {
387
+ var result = await picker.pick()
388
+ if (!result.ok) throw new Error(result.error.message)
389
+ path = result.value
390
+ } catch (problem) {
391
+ if (mounted.current) setError(new Error(T('s0.pickerFailed', { message: messageOf(problem) })))
392
+ } finally {
398
393
  if (mounted.current) setBusy('')
399
- connect(path)
400
- }, function () {
401
- if (!mounted.current) return
402
- setBusy('')
403
- setManual(true)
404
- })
394
+ }
395
+ if (mounted.current && path) return connect(path)
405
396
  }
406
397
 
407
398
  function submitManual() {
@@ -521,11 +512,6 @@ window.__ModuleLoader__.load({
521
512
  props.stale ? h('div', { className: 'gr-err' }, T('s0.stale', { path: props.stale })) : null,
522
513
  h('div', { className: 'gr-h2' }, T('s0.title')),
523
514
  h('div', { className: 'gr-body' }, T('s0.body')),
524
- h('div', { className: 'gr-steps' },
525
- h('div', { className: 'gr-step' }, h('b', null, '1'), T('s0.step1')),
526
- h('div', { className: 'gr-step' }, h('b', null, '2'), T('s0.step2')),
527
- h('div', { className: 'gr-step' }, h('b', null, '3'), T('s0.step3')),
528
- ),
529
515
  props.manual
530
516
  ? h('div', { className: 'gr-row' },
531
517
  h('input', {
@@ -544,7 +530,6 @@ window.__ModuleLoader__.load({
544
530
  ? h('button', { className: 'gr-btn gr-btn-ghost gr-btn-sm', disabled: props.busy !== '', onClick: props.onCancel }, T('s0.cancel'))
545
531
  : null,
546
532
  ),
547
- h('div', { className: 'gr-meta' }, T('s0.hint')),
548
533
  )
549
534
  }
550
535
 
@@ -1146,8 +1131,6 @@ window.__ModuleLoader__.load({
1146
1131
  function Footer() {
1147
1132
  return h('div', { className: 'gr-foot' },
1148
1133
  h('div', null, T('foot.privacy')),
1149
- h('div', null, T('foot.confirm')),
1150
- h('div', null, T('foot.data')),
1151
1134
  )
1152
1135
  }
1153
1136
 
@@ -1199,9 +1182,6 @@ window.__ModuleLoader__.load({
1199
1182
  '.gr-err{color:var(--dsw-alias-state-error-primary);font-size:12px;white-space:pre-wrap}',
1200
1183
  '.gr-ok{color:var(--dsw-alias-state-success-primary)}',
1201
1184
  '.gr-path{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:6px;padding:2px 6px;word-break:break-all}',
1202
- '.gr-steps{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}',
1203
- '.gr-step{border:1px solid var(--dsw-alias-border-l1);border-radius:10px;padding:12px;font-size:12px;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-base)}',
1204
- '.gr-step b{display:block;color:var(--dsw-alias-label-primary);font-size:12px;margin-bottom:2px}',
1205
1185
  '.gr-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(112px,1fr));gap:10px}',
1206
1186
  '.gr-stat{border:1px solid var(--dsw-alias-border-l1);border-radius:10px;padding:12px;background:var(--dsw-alias-bg-base);min-width:0}',
1207
1187
  '.gr-stat b{display:block;font-size:20px;font-weight:600;line-height:1.2}',
@@ -1213,7 +1193,7 @@ window.__ModuleLoader__.load({
1213
1193
  '.gr-itemtitle{flex:1 1 auto;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}',
1214
1194
  '.gr-code{white-space:pre-wrap;word-break:break-word;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l1);border-radius:8px;padding:10px 12px;font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12px;line-height:1.6;margin:0}',
1215
1195
  '.gr-foot{border-top:1px solid var(--dsw-alias-border-l1);padding-top:12px;color:var(--dsw-alias-label-secondary);font-size:12px;display:flex;flex-direction:column;gap:4px}',
1216
- '@media (max-width:560px){.gr-inner{padding:18px 14px 32px}.gr-head{flex-wrap:wrap}.gr-steps{grid-template-columns:1fr}.gr-stats{grid-template-columns:repeat(2,1fr)}.gr-stat:last-child:nth-child(odd){grid-column:1/-1}.gr-btn{align-self:stretch;justify-content:center}}',
1196
+ '@media (max-width:560px){.gr-inner{padding:18px 14px 32px}.gr-head{flex-wrap:wrap}.gr-stats{grid-template-columns:repeat(2,1fr)}.gr-stat:last-child:nth-child(odd){grid-column:1/-1}.gr-btn{align-self:stretch;justify-content:center}}',
1217
1197
  '@media (prefers-reduced-motion:reduce){.gr-btn{transition:none}}',
1218
1198
  ].join('\n')
1219
1199
 
@@ -1230,10 +1210,16 @@ window.__ModuleLoader__.load({
1230
1210
  console.warn('[grove] locale registration failed', error)
1231
1211
  }
1232
1212
  }
1233
- try {
1234
- services.workspace = ctx.get('uiWorkspace')
1235
- } catch (error) {
1236
- services.workspace = null
1213
+ if (typeof ctx.inject === 'function') {
1214
+ ctx.inject(['remote', 'remote.directoryPicker'], function (scoped) {
1215
+ var picker = scoped.remote.directoryPicker
1216
+ scoped.effect(function () {
1217
+ services.picker = picker
1218
+ return function () {
1219
+ if (services.picker === picker) services.picker = null
1220
+ }
1221
+ }, 'grove: directory picker')
1222
+ })
1237
1223
  }
1238
1224
  var slots = ctx.slots
1239
1225
  if (!slots || typeof slots.inject !== 'function' || typeof slots.register !== 'function') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-grove",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Explore with AI in DeepSeek Harness and grow knowledge you can revisit and revise in your own Obsidian vault",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -49,6 +49,7 @@
49
49
  "platform": "web",
50
50
  "immediately": true,
51
51
  "inject": [
52
+ "@deepseek-ai/dsh-api-remotes",
52
53
  "@deepseek-ai/dsh-client-ui-sidebar",
53
54
  "@deepseek-ai/dsh-client-ui-layout"
54
55
  ]