@uniqbit/mate-core 0.17.0-canary.8 → 0.17.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 (103) hide show
  1. package/package.json +11 -5
  2. package/src/cli/commands/artifact/finish/index.ts +0 -9
  3. package/src/cli/commands/artifact/finish/openspec.ts +2 -2
  4. package/src/cli/commands/artifact/finish/registry.ts +1 -1
  5. package/src/cli/commands/artifact/pending/discovery.ts +1 -1
  6. package/src/cli/commands/artifact/pending/index.ts +0 -16
  7. package/src/cli/commands/cap/graphify.ts +1 -1
  8. package/src/cli/commands/cap/index-cmd.ts +1 -1
  9. package/src/cli/commands/cap/tokensave.ts +4 -3
  10. package/src/cli/commands/companion/companion.ts +4 -0
  11. package/src/cli/commands/companion/hub.ts +2 -1
  12. package/src/cli/commands/companion/list.ts +2 -1
  13. package/src/cli/commands/companion/prepare.ts +2 -2
  14. package/src/cli/commands/companion/update.ts +334 -0
  15. package/src/cli/commands/doctor.ts +2 -1
  16. package/src/cli/commands/install.ts +59 -5
  17. package/src/cli/commands/launch/shared.ts +2 -1
  18. package/src/cli/commands/plugin/plugin.ts +4 -0
  19. package/src/cli/commands/plugin/verify.ts +25 -0
  20. package/src/cli/commands/report/highlight.ts +1 -4
  21. package/src/cli/commands/report/renderer.ts +0 -2
  22. package/src/cli/commands/studio/access.ts +201 -0
  23. package/src/cli/commands/studio/index.ts +207 -26
  24. package/src/cli/commands/studio/openspec-cli.ts +1 -1
  25. package/src/cli/commands/studio/selection.ts +127 -11
  26. package/src/cli/commands/studio/server.ts +355 -64
  27. package/src/cli/commands/studio/terminal-assets.ts +50 -0
  28. package/src/cli/commands/studio/terminal-launch.ts +71 -0
  29. package/src/cli/commands/studio/terminal.ts +593 -0
  30. package/src/cli/commands/studio/vault.ts +320 -75
  31. package/src/cli/commands/studio/views/client.ts +90 -9
  32. package/src/cli/commands/studio/views/companion-picker.tsx +9 -5
  33. package/src/cli/commands/studio/views/companion-selector.tsx +11 -7
  34. package/src/cli/commands/studio/views/document.tsx +411 -107
  35. package/src/cli/commands/studio/views/model.ts +14 -1
  36. package/src/cli/commands/studio/views/selection-fields.tsx +14 -0
  37. package/src/cli/commands/studio/views/styles.ts +106 -13
  38. package/src/cli/commands/studio/views/terminal.tsx +426 -0
  39. package/src/cli/commands/studio/views/vault/state.ts +42 -0
  40. package/src/cli/commands/studio/views/workflow/steps.ts +10 -3
  41. package/src/cli/commands/update.ts +11 -8
  42. package/src/cli/companion-link-wizard.tsx +1 -1
  43. package/src/cli/companion-selector.tsx +1 -1
  44. package/src/cli/launch-selector.tsx +1 -1
  45. package/src/cli/main.ts +2 -1
  46. package/src/cli/usage.ts +7 -3
  47. package/src/cli/write-json-stdout.ts +2 -2
  48. package/src/lib/components/spinner.tsx +2 -2
  49. package/src/lib/components/startup-progress.tsx +1 -1
  50. package/src/lib/context-mode-package.ts +1 -1
  51. package/src/lib/opencode-plugin-package.ts +3 -0
  52. package/src/lib/orchestrator/adapters/opencode.ts +53 -13
  53. package/src/lib/orchestrator/companion-hub.ts +3 -3
  54. package/src/lib/orchestrator/companion-registry-store.ts +1 -1
  55. package/src/lib/orchestrator/config-store.ts +2 -2
  56. package/src/lib/orchestrator/editor.ts +4 -12
  57. package/src/lib/orchestrator/engine-guard.ts +9 -1
  58. package/src/lib/orchestrator/projection-entries.ts +1 -1
  59. package/src/lib/orchestrator/projection-record.ts +1 -1
  60. package/src/lib/orchestrator/projection-types.ts +0 -4
  61. package/src/lib/orchestrator/repo-local-registry.ts +0 -1
  62. package/src/lib/orchestrator/root-context.ts +1 -1
  63. package/src/lib/orchestrator/setup-compatibilities.ts +1 -1
  64. package/src/lib/orchestrator/setup-preflight.ts +1 -1
  65. package/src/lib/orchestrator/types.ts +1 -1
  66. package/src/lib/orchestrator/working-repo-projection.ts +1 -1
  67. package/src/lib/orchestrator/workspace-inventory.ts +2 -2
  68. package/src/lib/package-paths.ts +1 -11
  69. package/src/lib/package-root.ts +43 -0
  70. package/src/lib/prebuilt-workspace.ts +1 -1
  71. package/src/lib/public-npm.ts +1 -1
  72. package/src/opencode/companion-hooks.ts +131 -153
  73. package/src/opencode/index.ts +12 -6
  74. package/src/opencode/tui.tsx +46 -49
  75. package/src/playbooks/companion-guidance.ts +1 -28
  76. package/src/runtime/companion-sync.ts +0 -3
  77. package/src/templates/capabilities/openspec-cap/mate-minimal/schema.yaml +2 -1
  78. package/src/templates/providers/opencode/opencode.json +6 -4
  79. package/src/tools/setup/__snapshots__/runtime-surface-golden.test.ts.snap +500 -408
  80. package/src/tools/setup/capabilities/context-mode.ts +45 -25
  81. package/src/tools/setup/capabilities/graphify-shared.ts +3 -3
  82. package/src/tools/setup/capabilities/graphify.ts +2 -2
  83. package/src/tools/setup/capabilities/openspec.ts +2 -7
  84. package/src/tools/setup/capabilities/react-doctor.ts +1 -1
  85. package/src/tools/setup/capabilities/rtk.ts +2 -2
  86. package/src/tools/setup/capabilities/tokensave.ts +98 -12
  87. package/src/tools/setup/context-services.ts +3 -6
  88. package/src/tools/setup/dynamic-plugins/declarations.ts +47 -0
  89. package/src/tools/setup/dynamic-plugins/frozen.ts +215 -0
  90. package/src/tools/setup/dynamic-plugins/hydrate.ts +1 -40
  91. package/src/tools/setup/dynamic-plugins/loader.ts +16 -0
  92. package/src/tools/setup/dynamic-plugins/policy.ts +55 -0
  93. package/src/tools/setup/dynamic-plugins/staging.ts +53 -0
  94. package/src/tools/setup/dynamic-plugins/verify.ts +70 -0
  95. package/src/tools/setup/mate.ts +1 -1
  96. package/src/tools/setup/providers/claude-format.ts +1 -1
  97. package/src/tools/setup/providers/claude.ts +1 -1
  98. package/src/tools/setup/providers/opencode-format.ts +220 -25
  99. package/src/tools/setup/providers/opencode.ts +63 -21
  100. package/src/tools/setup/runtime-documents.ts +9 -11
  101. package/src/tools/setup.ts +0 -4
  102. package/src/cli/commands/studio/views/pairings.tsx +0 -38
  103. package/src/templates/providers/opencode/tui.json +0 -3
@@ -16,21 +16,44 @@ export const COMPANION_PARAM = "companion";
16
16
  export const VIEW_PARAM = "view";
17
17
  export const REFRESH_PARAM = "refresh";
18
18
  export const FILE_PARAM = "path";
19
+ export const DIR_PARAM = "dir";
20
+
21
+ /** Every URL parameter Studio names; no other module writes one out. */
22
+ export const STUDIO_PARAMS: readonly string[] = [
23
+ COMPANION_PARAM,
24
+ VIEW_PARAM,
25
+ REFRESH_PARAM,
26
+ FILE_PARAM,
27
+ DIR_PARAM,
28
+ ];
19
29
 
20
30
  /** Filled into a prompt when no change is named, so a prompt is never half-written. */
21
31
  export const CHANGE_PLACEHOLDER = "<change-name>";
22
32
 
23
33
  const DIGEST_LENGTH = 10;
24
34
 
25
- export interface StudioSelection {
35
+ interface SelectionBase {
26
36
  companionDigest: string | null;
27
- view: StudioView;
28
- /**
29
- * One-shot: the refresh control asks for it, and it is never carried forward
30
- * into the URL another control builds. Switching a view is not a refresh.
31
- */
37
+ /** One-shot: only the `refresh` move sets it, and every other move clears it. */
32
38
  refresh: boolean;
39
+ }
40
+
41
+ export interface StudioVaultSelection extends SelectionBase {
42
+ view: "vault";
33
43
  openPath: string | null;
44
+ /** A folder of the listed tree; never looked up on disk. */
45
+ openDir: string | null;
46
+ }
47
+
48
+ export interface StudioPlainSelection extends SelectionBase {
49
+ view: Exclude<StudioView, "vault">;
50
+ }
51
+
52
+ export type StudioSelection = StudioVaultSelection | StudioPlainSelection;
53
+
54
+ export interface SelectionField {
55
+ name: string;
56
+ value: string;
34
57
  }
35
58
 
36
59
  /**
@@ -60,11 +83,104 @@ function readView(value: string | null): StudioView {
60
83
  return STUDIO_VIEWS.includes(value as StudioView) ? (value as StudioView) : "dashboard";
61
84
  }
62
85
 
63
- export function parseStudioSelection(url: URL): StudioSelection {
86
+ function readText(value: string | null): string | null {
87
+ return value?.trim() || null;
88
+ }
89
+
90
+ /** An empty or malformed digest selects no companion, as an unmatched one already does. */
91
+ function readDigest(value: string | null): string | null {
92
+ const digest = readText(value);
93
+ return digest && COMPANION_DIGEST_PATTERN.test(digest) ? digest : null;
94
+ }
95
+
96
+ function readBase(params: URLSearchParams): SelectionBase {
97
+ return {
98
+ companionDigest: readDigest(params.get(COMPANION_PARAM)),
99
+ refresh: params.get(REFRESH_PARAM) === "1",
100
+ };
101
+ }
102
+
103
+ function readVault(params: URLSearchParams): StudioVaultSelection {
104
+ return {
105
+ ...readBase(params),
106
+ view: "vault",
107
+ openPath: readText(params.get(FILE_PARAM)),
108
+ openDir: readText(params.get(DIR_PARAM)),
109
+ };
110
+ }
111
+
112
+ /** Forgiving: parameters the named view does not have are ignored. */
113
+ export function parse(url: URL): StudioSelection {
114
+ const view = readView(url.searchParams.get(VIEW_PARAM));
115
+ if (view === "vault") return readVault(url.searchParams);
116
+ return { ...readBase(url.searchParams), view };
117
+ }
118
+
119
+ /** For the `/api/vault/*` routes, which imply the vault view whatever `view` says. */
120
+ export function parseVaultSelection(url: URL): StudioVaultSelection {
121
+ return readVault(url.searchParams);
122
+ }
123
+
124
+ /** Drops the vault's target. */
125
+ export function switchView(selection: StudioSelection, view: StudioView): StudioSelection {
126
+ const base = { companionDigest: selection.companionDigest, refresh: false };
127
+ if (view === "vault") return { ...base, view, openPath: null, openDir: null };
128
+ return { ...base, view };
129
+ }
130
+
131
+ /** Keeps the view and drops the vault's target: it belongs to the companion being left. */
132
+ export function switchCompanion(
133
+ selection: StudioSelection,
134
+ digest: string | null,
135
+ ): StudioSelection {
136
+ return { ...switchView(selection, selection.view), companionDigest: digest };
137
+ }
138
+
139
+ export function openFile(selection: StudioSelection, path: string): StudioVaultSelection {
64
140
  return {
65
- companionDigest: url.searchParams.get(COMPANION_PARAM)?.trim() || null,
66
- view: readView(url.searchParams.get(VIEW_PARAM)),
67
- refresh: url.searchParams.get(REFRESH_PARAM) === "1",
68
- openPath: url.searchParams.get(FILE_PARAM)?.trim() || null,
141
+ companionDigest: selection.companionDigest,
142
+ refresh: false,
143
+ view: "vault",
144
+ openPath: path,
145
+ openDir: null,
69
146
  };
70
147
  }
148
+
149
+ /** `null` opens the companion root. */
150
+ export function openFolder(selection: StudioSelection, dir: string | null): StudioVaultSelection {
151
+ return {
152
+ companionDigest: selection.companionDigest,
153
+ refresh: false,
154
+ view: "vault",
155
+ openPath: null,
156
+ openDir: dir,
157
+ };
158
+ }
159
+
160
+ export function refresh(selection: StudioSelection): StudioSelection {
161
+ return { ...selection, refresh: true };
162
+ }
163
+
164
+ /** Omits defaults (the Dashboard view, an unset target), so URLs stay short. */
165
+ export function toFields(selection: StudioSelection): SelectionField[] {
166
+ const fields: SelectionField[] = [];
167
+ if (selection.companionDigest) {
168
+ fields.push({ name: COMPANION_PARAM, value: selection.companionDigest });
169
+ }
170
+ if (selection.view !== "dashboard") fields.push({ name: VIEW_PARAM, value: selection.view });
171
+ if (selection.view === "vault") {
172
+ if (selection.openPath) fields.push({ name: FILE_PARAM, value: selection.openPath });
173
+ if (selection.openDir) fields.push({ name: DIR_PARAM, value: selection.openDir });
174
+ }
175
+ if (selection.refresh) fields.push({ name: REFRESH_PARAM, value: "1" });
176
+ return fields;
177
+ }
178
+
179
+ export function toSearchParams(selection: StudioSelection): URLSearchParams {
180
+ return new URLSearchParams(toFields(selection).map(({ name, value }) => [name, value]));
181
+ }
182
+
183
+ export function toHref(selection: StudioSelection, route = "/"): string {
184
+ const query = toSearchParams(selection).toString();
185
+ return query ? `${route}?${query}` : route;
186
+ }