moqi-tui 0.2.0

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 (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +782 -0
  3. package/bin/moqi.mjs +40 -0
  4. package/cordis.patch.yml +41 -0
  5. package/lib/cross-find.js +217 -0
  6. package/lib/file-index.js +121 -0
  7. package/lib/fleet-sources.js +114 -0
  8. package/lib/index.js +3999 -0
  9. package/lib/persist.js +194 -0
  10. package/lib/plugins.js +371 -0
  11. package/lib/presence.js +144 -0
  12. package/lib/rename.js +35 -0
  13. package/lib/rewind.js +94 -0
  14. package/lib/sessions-store.js +134 -0
  15. package/lib/startup.js +92 -0
  16. package/lib/tui/atfile.js +154 -0
  17. package/lib/tui/export.js +48 -0
  18. package/lib/tui/fleet.js +346 -0
  19. package/lib/tui/i18n.js +201 -0
  20. package/lib/tui/jobs.js +65 -0
  21. package/lib/tui/keys.js +205 -0
  22. package/lib/tui/markdown.js +368 -0
  23. package/lib/tui/mcp.js +95 -0
  24. package/lib/tui/panels.js +231 -0
  25. package/lib/tui/screen.js +156 -0
  26. package/lib/tui/state.js +502 -0
  27. package/lib/tui/stream.js +109 -0
  28. package/lib/tui/text.js +173 -0
  29. package/lib/tui/theme.js +183 -0
  30. package/lib/tui/themes.js +153 -0
  31. package/lib/tui/tooldetail.js +140 -0
  32. package/lib/tui/view.js +830 -0
  33. package/lib/tui/vim.js +222 -0
  34. package/lib/tui-host-core.js +141 -0
  35. package/lib/tui-host.js +48 -0
  36. package/lib/types/cross-find.d.ts +66 -0
  37. package/lib/types/file-index.d.ts +34 -0
  38. package/lib/types/fleet-sources.d.ts +34 -0
  39. package/lib/types/index.d.ts +51 -0
  40. package/lib/types/persist.d.ts +116 -0
  41. package/lib/types/plugins.d.ts +218 -0
  42. package/lib/types/presence.d.ts +48 -0
  43. package/lib/types/rename.d.ts +32 -0
  44. package/lib/types/rewind.d.ts +75 -0
  45. package/lib/types/sessions-store.d.ts +46 -0
  46. package/lib/types/startup.d.ts +45 -0
  47. package/lib/types/tui/atfile.d.ts +90 -0
  48. package/lib/types/tui/export.d.ts +18 -0
  49. package/lib/types/tui/fleet.d.ts +209 -0
  50. package/lib/types/tui/i18n.d.ts +34 -0
  51. package/lib/types/tui/jobs.d.ts +28 -0
  52. package/lib/types/tui/keys.d.ts +52 -0
  53. package/lib/types/tui/markdown.d.ts +14 -0
  54. package/lib/types/tui/mcp.d.ts +34 -0
  55. package/lib/types/tui/panels.d.ts +125 -0
  56. package/lib/types/tui/screen.d.ts +79 -0
  57. package/lib/types/tui/state.d.ts +323 -0
  58. package/lib/types/tui/stream.d.ts +78 -0
  59. package/lib/types/tui/text.d.ts +28 -0
  60. package/lib/types/tui/theme.d.ts +87 -0
  61. package/lib/types/tui/themes.d.ts +70 -0
  62. package/lib/types/tui/tooldetail.d.ts +45 -0
  63. package/lib/types/tui/view.d.ts +163 -0
  64. package/lib/types/tui/vim.d.ts +64 -0
  65. package/lib/types/tui-host-core.d.ts +62 -0
  66. package/lib/types/tui-host.d.ts +42 -0
  67. package/lib/types/version.d.ts +8 -0
  68. package/lib/types/voice.d.ts +227 -0
  69. package/lib/version.js +32 -0
  70. package/lib/voice.js +405 -0
  71. package/package.json +119 -0
  72. package/scripts/harness-root.mjs +88 -0
  73. package/scripts/install-profile.mjs +133 -0
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Create (or refresh) the `tui` profile in the Harness home and point it at
3
+ * this checkout.
4
+ *
5
+ * A profile is a directory under `$DSH_HOME/profiles` holding a `package.json`
6
+ * whose `dsh.profile.bundles` lists the patch layers to compose, its own
7
+ * `cordis.patch.yml`, and a `pnpm-workspace.yaml`. This writes all three with
8
+ * an absolute link to wherever this repository actually lives, which is why it
9
+ * is a script rather than a `cp` of a template with a relative path in it.
10
+ *
11
+ * Run with: node scripts/install-profile.mjs [profileName]
12
+ */
13
+
14
+ import { execFileSync } from 'node:child_process'
15
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
16
+ import { join, resolve } from 'node:path'
17
+ import { homedir } from 'node:os'
18
+ import { findDshRoot, linkHarnessPackages } from './harness-root.mjs'
19
+
20
+ const profileName = process.argv[2] ?? 'tui'
21
+ if (profileName === '' || profileName.includes('/') || profileName.includes('\\')) {
22
+ console.error(`install-profile: invalid profile name ${JSON.stringify(profileName)}`)
23
+ process.exit(1)
24
+ }
25
+
26
+ const repoRoot = resolve(import.meta.dirname, '..')
27
+ const packageName = JSON.parse(readFileSync(join(repoRoot, 'package.json'), 'utf8')).name
28
+
29
+ // The Harness home: $DSH_HOME when set and non-blank, else ~/.dsh.
30
+ const fromEnvironment = process.env.DSH_HOME
31
+ const dshHome =
32
+ fromEnvironment !== undefined && fromEnvironment.trim() !== ''
33
+ ? resolve(fromEnvironment)
34
+ : join(homedir(), '.dsh')
35
+
36
+ const profileDir = join(dshHome, 'profiles', profileName)
37
+ mkdirSync(profileDir, { recursive: true })
38
+
39
+ // The bundle needs its build output: the manifest's `main` points into lib/.
40
+ if (!existsSync(join(repoRoot, 'lib', 'index.js'))) {
41
+ console.error('install-profile: lib/ is missing — run `npm run build` (or `pnpm run build`) first.')
42
+ process.exit(1)
43
+ }
44
+
45
+ const manifestPath = join(profileDir, 'package.json')
46
+ const manifest = {
47
+ name: `dsh-profile-${profileName}`,
48
+ private: true,
49
+ dependencies: {
50
+ // Absolute, so the profile keeps resolving wherever the Harness home is.
51
+ [packageName]: `link:${repoRoot}`,
52
+ },
53
+ dsh: {
54
+ profile: {
55
+ bundles: ['@deepseek-ai/dsh-base', packageName],
56
+ // This bundle disables HMR: a reload repainting under the alternate
57
+ // screen would corrupt it, so patches apply on restart.
58
+ patchReload: 'startup',
59
+ },
60
+ },
61
+ }
62
+ writeFileSync(manifestPath, `${JSON.stringify(manifest, undefined, 2)}\n`)
63
+
64
+ const workspacePath = join(profileDir, 'pnpm-workspace.yaml')
65
+ if (!existsSync(workspacePath)) {
66
+ writeFileSync(workspacePath, 'packages:\n - .\n\nnodeLinker: hoisted\nautoInstallPeers: false\n')
67
+ }
68
+
69
+ const patchPath = join(profileDir, 'cordis.patch.yml')
70
+ if (!existsSync(patchPath)) {
71
+ // The loader requires a top-level YAML array, so a file of nothing but
72
+ // comments is a parse error rather than "no patches" — the empty list has to
73
+ // be written out explicitly.
74
+ writeFileSync(
75
+ patchPath,
76
+ [
77
+ '# Your own patch layer for this profile. It composes last, so anything',
78
+ '# set here wins over the bundle patches. Replace [] with entries, e.g.',
79
+ '#',
80
+ '# - id: tui-app',
81
+ '# config:',
82
+ '# contextLimit: 131072',
83
+ '# thinking: true',
84
+ '[]',
85
+ '',
86
+ ].join('\n'),
87
+ )
88
+ }
89
+
90
+ console.log(`install-profile: wrote ${profileDir}`)
91
+
92
+ // pnpm is what the Harness itself uses for profiles; npm also works.
93
+ const manager = hasCommand('pnpm') ? 'pnpm' : 'npm'
94
+ try {
95
+ execFileSync(manager, ['install'], { cwd: profileDir, stdio: 'inherit' })
96
+ } catch (error) {
97
+ console.error(`install-profile: ${manager} install failed: ${error.message}`)
98
+ console.error(`install-profile: run it yourself in ${profileDir}`)
99
+ process.exit(1)
100
+ }
101
+
102
+ // The profile links this package from wherever it lives, so Node resolves its
103
+ // `@deepseek-ai/*` imports from the package's own directory — where, on a
104
+ // clean machine, those packages do not exist. Linking the harness's own copies
105
+ // in is what makes a freshly installed app boot at all; it is idempotent, and
106
+ // it deliberately keeps the harness's copies rather than installing a second
107
+ // `@deepseek-ai/cordis`, which would be a different Service class.
108
+ const dshRoot = findDshRoot()
109
+ if (dshRoot === undefined) {
110
+ console.warn('install-profile: no `dsh` installation found to link harness packages from.')
111
+ console.warn('install-profile: install @deepseek-ai/dsh, or set DSH_INSTALL_ROOT to its package directory.')
112
+ } else {
113
+ const { linked, failed } = linkHarnessPackages(repoRoot, dshRoot)
114
+ if (linked.length > 0) {
115
+ console.log(`install-profile: linked ${String(linked.length)} harness packages into the app`)
116
+ }
117
+ if (failed.length > 0) {
118
+ console.warn(`install-profile: could not link ${failed.join(', ')} — the app may fail to boot`)
119
+ console.warn(`install-profile: re-run with permission to write ${repoRoot}/node_modules`)
120
+ }
121
+ }
122
+
123
+ console.log(`install-profile: done — run it with: dsh --profile ${profileName}`)
124
+
125
+ /** Whether a command exists on PATH. */
126
+ function hasCommand(name) {
127
+ try {
128
+ execFileSync('sh', ['-c', `command -v ${name}`], { stdio: 'ignore' })
129
+ return true
130
+ } catch {
131
+ return false
132
+ }
133
+ }