@kdonev/termscape 0.1.0 → 0.1.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 (78) hide show
  1. package/README.md +176 -13
  2. package/dist/agents/detect.d.ts +27 -0
  3. package/dist/agents/detect.d.ts.map +1 -0
  4. package/dist/agents/detect.js +210 -0
  5. package/dist/agents/detect.js.map +1 -0
  6. package/dist/agents/profiles.d.ts +110 -0
  7. package/dist/agents/profiles.d.ts.map +1 -1
  8. package/dist/agents/profiles.js +215 -0
  9. package/dist/agents/profiles.js.map +1 -1
  10. package/dist/agents/templates.d.ts +85 -0
  11. package/dist/agents/templates.d.ts.map +1 -0
  12. package/dist/agents/templates.js +133 -0
  13. package/dist/agents/templates.js.map +1 -0
  14. package/dist/agents/wiring.d.ts +30 -1
  15. package/dist/agents/wiring.d.ts.map +1 -1
  16. package/dist/agents/wiring.js +179 -10
  17. package/dist/agents/wiring.js.map +1 -1
  18. package/dist/cli.js +41 -14
  19. package/dist/cli.js.map +1 -1
  20. package/dist/db/migrations.d.ts.map +1 -1
  21. package/dist/db/migrations.js +55 -0
  22. package/dist/db/migrations.js.map +1 -1
  23. package/dist/db/store.d.ts +41 -0
  24. package/dist/db/store.d.ts.map +1 -1
  25. package/dist/db/store.js +75 -2
  26. package/dist/db/store.js.map +1 -1
  27. package/dist/hub.d.ts +227 -6
  28. package/dist/hub.d.ts.map +1 -1
  29. package/dist/hub.js +504 -33
  30. package/dist/hub.js.map +1 -1
  31. package/dist/hub.tgz +0 -0
  32. package/dist/mcp/server.d.ts +2 -0
  33. package/dist/mcp/server.d.ts.map +1 -1
  34. package/dist/mcp/server.js +19 -2
  35. package/dist/mcp/server.js.map +1 -1
  36. package/dist/protocol/domain.d.ts +87 -0
  37. package/dist/protocol/domain.d.ts.map +1 -1
  38. package/dist/protocol/domain.js +104 -0
  39. package/dist/protocol/domain.js.map +1 -1
  40. package/dist/protocol/mcp-tools.d.ts +30 -0
  41. package/dist/protocol/mcp-tools.d.ts.map +1 -1
  42. package/dist/protocol/mcp-tools.js +50 -0
  43. package/dist/protocol/mcp-tools.js.map +1 -1
  44. package/dist/protocol/peer.d.ts +36 -0
  45. package/dist/protocol/peer.d.ts.map +1 -1
  46. package/dist/protocol/peer.js +35 -1
  47. package/dist/protocol/peer.js.map +1 -1
  48. package/dist/protocol/ws.d.ts +254 -0
  49. package/dist/protocol/ws.d.ts.map +1 -1
  50. package/dist/protocol/ws.js +160 -5
  51. package/dist/protocol/ws.js.map +1 -1
  52. package/dist/remote/lan.d.ts +45 -0
  53. package/dist/remote/lan.d.ts.map +1 -1
  54. package/dist/remote/lan.js +44 -0
  55. package/dist/remote/lan.js.map +1 -1
  56. package/dist/remote/peer-serve.d.ts.map +1 -1
  57. package/dist/remote/peer-serve.js +31 -3
  58. package/dist/remote/peer-serve.js.map +1 -1
  59. package/dist/remote/peer.d.ts +7 -0
  60. package/dist/remote/peer.d.ts.map +1 -1
  61. package/dist/remote/peer.js +22 -0
  62. package/dist/remote/peer.js.map +1 -1
  63. package/dist/remote/registry.d.ts +69 -2
  64. package/dist/remote/registry.d.ts.map +1 -1
  65. package/dist/remote/registry.js +134 -10
  66. package/dist/remote/registry.js.map +1 -1
  67. package/dist/server.d.ts +22 -3
  68. package/dist/server.d.ts.map +1 -1
  69. package/dist/server.js +237 -117
  70. package/dist/server.js.map +1 -1
  71. package/dist/session/manager.d.ts +44 -4
  72. package/dist/session/manager.d.ts.map +1 -1
  73. package/dist/session/manager.js +161 -34
  74. package/dist/session/manager.js.map +1 -1
  75. package/package.json +1 -1
  76. package/web/assets/{index-BOqZOoep.js → index-Bq_Y0JcC.js} +6 -6
  77. package/web/assets/{index-B2JtCtHa.css → index-DQYDkOwJ.css} +1 -1
  78. package/web/index.html +2 -2
@@ -11,6 +11,33 @@ function defaultShell() {
11
11
  * Built-in profiles. All Claude Code flags here are verified against the CLI:
12
12
  * --mcp-config, --strict-mcp-config, --session-id, --settings,
13
13
  * --append-system-prompt-file, --resume.
14
+ *
15
+ * Codex and Gemini are wired too, and every flag and key below was verified
16
+ * against the CLI actually installed - codex-cli 0.153.4 and gemini 0.58.0 -
17
+ * rather than written from memory. Both reach the hub the same way Claude
18
+ * Code does, over one streamable-HTTP MCP server carrying a bearer token, and
19
+ * neither needs a byte written to config the user owns:
20
+ *
21
+ * - **Codex** takes `-c <dotted.key>=<toml>` on any invocation, so the server
22
+ * is declared in argv for the one run. The token is *not* in argv - it goes
23
+ * in the environment, and `bearer_token_env_var` names the variable to read
24
+ * it from, which keeps it out of every process listing on the machine.
25
+ * - **Gemini** has no per-run config flag, but
26
+ * `GEMINI_CLI_SYSTEM_SETTINGS_PATH` repoints its system settings layer at a
27
+ * file of our choosing, which the hub generates per session.
28
+ *
29
+ * - **opencode** turned out to be the least invasive of the three and was
30
+ * assumed to be the hardest. It reads its entire config from
31
+ * `OPENCODE_CONFIG_CONTENT`, so nothing is written anywhere at all, and what
32
+ * it is given is merged with the user's own config rather than replacing it.
33
+ * The assumption that it had no per-run route came from reading
34
+ * `opencode mcp add` - which does write to the user's file, and ignores
35
+ * `OPENCODE_CONFIG` when it does - and mistaking that command for the only
36
+ * way in.
37
+ *
38
+ * `shell` is the only profile left that is not an agent, and it is not one in
39
+ * a way no flag can fix: it runs a shell, so text typed at it is executed
40
+ * rather than read.
14
41
  */
15
42
  export const BUILTIN_PROFILES = {
16
43
  claude: {
@@ -32,6 +59,19 @@ export const BUILTIN_PROFILES = {
32
59
  mcp: true,
33
60
  status: 'hooks',
34
61
  inject: 'bracketed',
62
+ versionArgs: ['--version'],
63
+ /*
64
+ * Claude Code has no listing command, so this is the declared half of
65
+ * "ask where you can, declare where you cannot". Exactly the aliases
66
+ * `claude --help` names for --model; a full name like `claude-fable-5` is
67
+ * accepted too, which is why a template must not be limited to this list.
68
+ */
69
+ models: ['fable', 'opus', 'sonnet'],
70
+ // Both verified against `claude --help`: --model takes an alias or a full
71
+ // name, --effort takes low, medium, high, xhigh or max.
72
+ modelArgs: ['--model', '{{model}}'],
73
+ effortArgs: ['--effort', '{{effort}}'],
74
+ efforts: ['low', 'medium', 'high', 'xhigh', 'max'],
35
75
  // Resume swaps --session-id for --resume; everything else is re-templated
36
76
  // identically, and crucially the session is relaunched in the same cwd,
37
77
  // because Claude Code keys its conversation store by working directory.
@@ -47,6 +87,151 @@ export const BUILTIN_PROFILES = {
47
87
  '{{brief_path}}',
48
88
  ],
49
89
  },
90
+ opencode: {
91
+ id: 'opencode',
92
+ description: 'opencode TUI, wired to the hub MCP endpoint',
93
+ command: 'opencode',
94
+ // Bare, which is its default subcommand and starts the TUI. `run` is the
95
+ // one-shot form and is not what a window on the canvas wants.
96
+ args: [],
97
+ /*
98
+ * The least invasive of the four, and the one that was assumed hardest.
99
+ * opencode reads its whole config from this variable, so there is no file
100
+ * anywhere - not even one of ours - and it is *merged* with the user's own
101
+ * config rather than replacing it, so their models, themes and their own
102
+ * MCP servers survive the session.
103
+ *
104
+ * Note what this deliberately does not use: `opencode mcp add` writes to
105
+ * ~/.config/opencode/opencode.json and ignores OPENCODE_CONFIG while doing
106
+ * it. Setting this variable also stops opencode writing its default config
107
+ * file on start, so a session leaves nothing behind at all.
108
+ */
109
+ env: { OPENCODE_CONFIG_CONTENT: '{{opencode_config}}' },
110
+ // `opencode models` writes ~/.config/opencode/opencode.jsonc when it finds
111
+ // no config at all, and detection runs on machines whose owner may never
112
+ // have run opencode by hand. An empty config is still a config, so this
113
+ // suppresses that without changing what the probe reports.
114
+ probeEnv: { OPENCODE_CONFIG_CONTENT: '{}' },
115
+ mcp: true,
116
+ brief: 'typed',
117
+ status: 'heuristic',
118
+ inject: 'bracketed',
119
+ versionArgs: ['--version'],
120
+ // Real enumeration: one provider/model per line, 395 of them on the
121
+ // machine this was written on.
122
+ modelsArgs: ['models'],
123
+ // `-m provider/model` is a top-level option, so it applies to the TUI and
124
+ // not only to `run`. Verified against `opencode --help`.
125
+ modelArgs: ['-m', '{{model}}'],
126
+ // No effortArgs on purpose: `--variant` is documented under `opencode run`
127
+ // and is not a top-level option, so the TUI this profile starts does not
128
+ // take one. A template asking for an effort here is refused at load.
129
+ },
130
+ codex: {
131
+ id: 'codex',
132
+ description: 'Codex CLI, wired to the hub MCP endpoint',
133
+ command: 'codex',
134
+ /*
135
+ * Bare, which starts the interactive TUI - `exec` is the one-shot form and
136
+ * is not what a window on the canvas wants.
137
+ *
138
+ * The two `-c` overrides are exactly the table `codex mcp add --url` would
139
+ * have written into ~/.codex/config.toml, except they live for one run and
140
+ * touch nothing. The value after `=` is parsed as TOML, which is why the
141
+ * URL is quoted.
142
+ */
143
+ args: [
144
+ '-c',
145
+ 'mcp_servers.termscape.url="{{mcp_url}}"',
146
+ '-c',
147
+ 'mcp_servers.termscape.bearer_token_env_var="TERMSCAPE_TOKEN"',
148
+ ],
149
+ // The token is named here rather than written into argv: `-c` values land
150
+ // in the process command line, where every other user on the machine can
151
+ // read them.
152
+ env: { TERMSCAPE_TOKEN: '{{token}}' },
153
+ mcp: true,
154
+ brief: 'typed',
155
+ status: 'heuristic',
156
+ inject: 'bracketed',
157
+ versionArgs: ['--version'],
158
+ /*
159
+ * `codex debug models` does render the real catalog, but it is a debug
160
+ * command by its own description and it answers with 500KB of JSON that
161
+ * also carries every model's system prompt - not the one-per-line stdout
162
+ * `modelsArgs` reads. So this is the declared half of "ask where you can,
163
+ * declare where you cannot": the slugs that catalog marks
164
+ * `visibility: "list"`. A full name not in this list is still accepted,
165
+ * which is why a template must not be limited to it.
166
+ */
167
+ models: ['gpt-6-astra', 'gpt-5.6-sol', 'gpt-5.6-terra', 'gpt-5.6-luna', 'gpt-5.5', 'gpt-5.2'],
168
+ modelArgs: ['-m', '{{model}}'],
169
+ /*
170
+ * Codex has no `--effort`; reasoning depth is a config key, and it takes
171
+ * the same `-c` route as the MCP server above. Verified by reading it back
172
+ * off the `reasoning effort:` line of the session header.
173
+ *
174
+ * The levels are the union of `supported_reasoning_levels` across the
175
+ * listed models. They are per model in the catalog and Codex forwards
176
+ * whatever it is given without checking, so this list is what the dialog
177
+ * offers and never a limit the hub enforces.
178
+ */
179
+ effortArgs: ['-c', 'model_reasoning_effort="{{effort}}"'],
180
+ efforts: ['low', 'medium', 'high', 'xhigh', 'max', 'ultra'],
181
+ /*
182
+ * No resumeArgs, and not an oversight. `codex resume` takes a session id,
183
+ * but Codex mints that id itself and offers no way to be handed one, so
184
+ * the hub cannot record up front what it would have to ask for later.
185
+ * `--last` is the alternative and it resolves to "the most recent session
186
+ * in this cwd", which is the wrong agent as soon as a workspace holds two
187
+ * of them. Better to say plainly it restarts clean.
188
+ */
189
+ },
190
+ gemini: {
191
+ id: 'gemini',
192
+ description: 'Gemini CLI, wired to the hub MCP endpoint',
193
+ command: 'gemini',
194
+ /*
195
+ * Gemini refuses to start MCP servers in a folder it does not trust, and
196
+ * says so only as a warning on stderr - the agent would come up looking
197
+ * fine with no tools. `--skip-trust` trusts the workspace for this session
198
+ * and writes nothing; the alternative, turning folder trust off in the
199
+ * settings file below, would disable the check for everything else too.
200
+ */
201
+ args: ['--skip-trust'],
202
+ // No `--mcp-config` equivalent exists. This repoints the *system* settings
203
+ // layer - normally a machine-wide file - at the per-session one the hub
204
+ // generates, so ~/.gemini/settings.json is never opened, let alone written.
205
+ env: { GEMINI_CLI_SYSTEM_SETTINGS_PATH: '{{gemini_settings_path}}' },
206
+ mcp: true,
207
+ brief: 'typed',
208
+ status: 'heuristic',
209
+ inject: 'bracketed',
210
+ versionArgs: ['--version'],
211
+ // Declared: there is no `gemini models`. These are the model constants the
212
+ // CLI itself names, minus the ones it uses internally for embeddings and
213
+ // its visual agent, which are not things to point an agent window at.
214
+ models: [
215
+ 'gemini-3.1-pro-preview',
216
+ 'gemini-3-pro-preview',
217
+ 'gemini-3.5-flash',
218
+ 'gemini-3-flash',
219
+ 'gemini-3.1-flash-lite',
220
+ 'gemini-2.5-pro',
221
+ 'gemini-2.5-flash',
222
+ ],
223
+ modelArgs: ['-m', '{{model}}'],
224
+ /*
225
+ * No effortArgs: `gemini --help` documents no reasoning-effort option, so
226
+ * a template naming one for this agent is refused at load rather than
227
+ * dropped at launch.
228
+ *
229
+ * No resumeArgs either, for a narrower reason than Codex's. `--session-id`
230
+ * does accept a UUID of our choosing, but `--resume` takes "latest" or an
231
+ * index into a list - never that UUID - so the id the hub could record is
232
+ * not an id it could resume by.
233
+ */
234
+ },
50
235
  shell: {
51
236
  id: 'shell',
52
237
  description: 'Plain terminal, no agent wiring',
@@ -54,11 +239,29 @@ export const BUILTIN_PROFILES = {
54
239
  args: [],
55
240
  env: {},
56
241
  mcp: false,
242
+ // Said out loud rather than left to the default, because this is the one
243
+ // profile where being typed at is actively harmful: a shell runs what it
244
+ // is given. It can still be *sent* a message - the router writes to any
245
+ // running window - and that is the human's business, not the hub's.
246
+ brief: 'none',
57
247
  status: 'heuristic',
58
248
  readyHint: '[$#>%] ?$',
59
249
  inject: 'raw',
250
+ // Nothing to detect: it is whatever COMSPEC or SHELL points at, it is
251
+ // always there, and asking a shell its version means something different
252
+ // on every platform.
60
253
  },
61
254
  };
255
+ /**
256
+ * How this profile's brief travels, with the defaults applied.
257
+ *
258
+ * One place, because three callers need the same answer and the interesting
259
+ * part is the default rather than the field: absent means `flag` for a wired
260
+ * agent and `none` for an unwired one.
261
+ */
262
+ export function briefMode(p) {
263
+ return p.brief ?? (p.mcp ? 'flag' : 'none');
264
+ }
62
265
  export class ProfileRegistry {
63
266
  profiles;
64
267
  constructor(profiles) {
@@ -74,6 +277,10 @@ export class ProfileRegistry {
74
277
  for (const [id, v] of Object.entries(raw)) {
75
278
  if (typeof v !== 'object' || v === null)
76
279
  continue;
280
+ // `[template.reviewer]` parses as one table named `template`, and it
281
+ // belongs to TemplateRegistry rather than here.
282
+ if (id === 'template')
283
+ continue;
77
284
  const base = merged[id];
78
285
  merged[id] = {
79
286
  id,
@@ -85,7 +292,15 @@ export class ProfileRegistry {
85
292
  status: v.status ?? base?.status ?? 'heuristic',
86
293
  readyHint: v.ready_hint ?? v.readyHint ?? base?.readyHint,
87
294
  inject: v.inject ?? base?.inject ?? 'bracketed',
295
+ brief: v.brief ?? base?.brief,
88
296
  resumeArgs: v.resume_args ?? v.resumeArgs ?? base?.resumeArgs,
297
+ probeEnv: v.probe_env ?? v.probeEnv ?? base?.probeEnv,
298
+ versionArgs: v.version_args ?? v.versionArgs ?? base?.versionArgs,
299
+ modelsArgs: v.models_args ?? v.modelsArgs ?? base?.modelsArgs,
300
+ models: v.models ?? base?.models,
301
+ modelArgs: v.model_args ?? v.modelArgs ?? base?.modelArgs,
302
+ effortArgs: v.effort_args ?? v.effortArgs ?? base?.effortArgs,
303
+ efforts: v.efforts ?? base?.efforts,
89
304
  };
90
305
  }
91
306
  }
@@ -1 +1 @@
1
- {"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../src/agents/profiles.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../src/agents/profiles.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import type { AgentTemplateInfo, TemplateSource } from '../protocol/index.js';
2
+ import type { Store } from '../db/store.js';
3
+ import type { ProfileRegistry } from './profiles.js';
4
+ /**
5
+ * A template is an agent plus a model, an effort and an opening instruction.
6
+ *
7
+ * Starting an agent used to ask exactly one question - which CLI - and
8
+ * everything that actually distinguishes one agent from another was missing.
9
+ * A template is a saved answer to all four, picked once instead of typed every
10
+ * time.
11
+ *
12
+ * On the words, because this file cannot be written without settling them:
13
+ *
14
+ * - **agent** is the CLI program, which the code calls a *profile*. That name
15
+ * stays internal: it is the recipe for launching one CLI.
16
+ * - **template** is what a human picks from a list.
17
+ * - **session** is one running instance, with an address and a window.
18
+ *
19
+ * A template that names only an agent is exactly today's behaviour, which is
20
+ * why every profile gets one for free and nothing that works now stops
21
+ * working.
22
+ */
23
+ export interface AgentTemplate {
24
+ id: string;
25
+ description: string;
26
+ /** Profile id. */
27
+ agent: string;
28
+ model?: string;
29
+ effort?: string;
30
+ /**
31
+ * Typed into the terminal once the CLI is up, not written into argv - in
32
+ * argv it would be a different thing entirely, and written immediately it
33
+ * lands before the program is reading.
34
+ */
35
+ prompt?: string;
36
+ /**
37
+ * Why this template cannot be used, when it cannot.
38
+ *
39
+ * Kept rather than dropped, for the same reason a missing agent stays in the
40
+ * list: a template that silently vanished looks like the config was ignored.
41
+ * A template asking for an effort on an agent that has no effort setting is
42
+ * a configuration error worth reporting here, at load, and not a flag
43
+ * quietly dropped at launch.
44
+ */
45
+ error?: string;
46
+ /**
47
+ * Where this one came from, which is what decides whether the panel may
48
+ * edit it.
49
+ *
50
+ * - `derived` — the free template every agent gets under its own name.
51
+ * Nothing is stored for it, so editing one means creating a stored
52
+ * template that shadows it, and there is nothing to remove.
53
+ * - `stored` — made from the panel, in `state.db`. Editable and removable.
54
+ * - `file` — declared in `~/.termscape/agents.toml`. Read-only here: it is
55
+ * the user's file and the hub does not write it.
56
+ */
57
+ source: TemplateSource;
58
+ }
59
+ /**
60
+ * Check a template against the agent it names.
61
+ *
62
+ * Returns the reason it cannot be used, or null. This is where "the agent
63
+ * declares how to spell it" is enforced: a template holds *values*, and a
64
+ * value nobody can spell on the command line is not a template, it is a typo
65
+ * that would otherwise be discovered at launch.
66
+ */
67
+ export declare function validate(t: AgentTemplate, profiles: ProfileRegistry): string | null;
68
+ export declare class TemplateRegistry {
69
+ private readonly templates;
70
+ constructor(templates: Record<string, AgentTemplate>);
71
+ /**
72
+ * One bare template per agent, overlaid with `[template.x]` from
73
+ * ~/.termscape/agents.toml.
74
+ *
75
+ * A broken file falls back to the bare set rather than taking the hub down,
76
+ * exactly as the profile loader does - the two live in the same file, and
77
+ * failing differently for the two halves of it would be its own surprise.
78
+ */
79
+ static load(profiles: ProfileRegistry, store?: Store): TemplateRegistry;
80
+ get(id: string): AgentTemplate | null;
81
+ list(): AgentTemplate[];
82
+ /** What the browser is given to build the picker from. */
83
+ info(): AgentTemplateInfo[];
84
+ }
85
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/agents/templates.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAE7E,OAAO,KAAK,EAAE,KAAK,EAAkB,MAAM,gBAAgB,CAAC;AAC5D,OAAO,KAAK,EAAgB,eAAe,EAAE,MAAM,eAAe,CAAC;AAEnE;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;OAUG;IACH,MAAM,EAAE,cAAc,CAAC;CACxB;AAyBD;;;;;;;GAOG;AACH,wBAAgB,QAAQ,CACtB,CAAC,EAAE,aAAa,EAChB,QAAQ,EAAE,eAAe,GACxB,MAAM,GAAG,IAAI,CAUf;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAgC;gBAE9C,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC;IAIpD;;;;;;;OAOG;IACH,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,eAAe,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,gBAAgB;IA2DvE,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI;IAIrC,IAAI,IAAI,aAAa,EAAE;IAIvB,0DAA0D;IAC1D,IAAI,IAAI,iBAAiB,EAAE;CAY5B"}
@@ -0,0 +1,133 @@
1
+ import { readFileSync, existsSync } from 'node:fs';
2
+ import { parse as parseToml } from 'smol-toml';
3
+ import { paths } from '../paths.js';
4
+ /** The trivial template for a profile: this agent, nothing else specified. */
5
+ function bare(profile) {
6
+ return {
7
+ id: profile.id,
8
+ description: profile.description,
9
+ agent: profile.id,
10
+ source: 'derived',
11
+ };
12
+ }
13
+ /** One the user made from the panel, as it comes out of the database. */
14
+ function fromStored(t, profiles) {
15
+ return {
16
+ id: t.id,
17
+ description: t.description ?? profiles.get(t.agent)?.description ?? t.id,
18
+ agent: t.agent,
19
+ model: t.model ?? undefined,
20
+ effort: t.effort ?? undefined,
21
+ prompt: t.prompt ?? undefined,
22
+ source: 'stored',
23
+ };
24
+ }
25
+ /**
26
+ * Check a template against the agent it names.
27
+ *
28
+ * Returns the reason it cannot be used, or null. This is where "the agent
29
+ * declares how to spell it" is enforced: a template holds *values*, and a
30
+ * value nobody can spell on the command line is not a template, it is a typo
31
+ * that would otherwise be discovered at launch.
32
+ */
33
+ export function validate(t, profiles) {
34
+ const agent = profiles.get(t.agent);
35
+ if (!agent)
36
+ return `unknown agent "${t.agent}"`;
37
+ if (t.model !== undefined && !agent.modelArgs) {
38
+ return `${t.agent} does not take a model on the command line`;
39
+ }
40
+ if (t.effort !== undefined && !agent.effortArgs) {
41
+ return `${t.agent} has no effort setting`;
42
+ }
43
+ return null;
44
+ }
45
+ export class TemplateRegistry {
46
+ templates;
47
+ constructor(templates) {
48
+ this.templates = templates;
49
+ }
50
+ /**
51
+ * One bare template per agent, overlaid with `[template.x]` from
52
+ * ~/.termscape/agents.toml.
53
+ *
54
+ * A broken file falls back to the bare set rather than taking the hub down,
55
+ * exactly as the profile loader does - the two live in the same file, and
56
+ * failing differently for the two halves of it would be its own surprise.
57
+ */
58
+ static load(profiles, store) {
59
+ const merged = Object.fromEntries(profiles.list().map((p) => [p.id, bare(p)]));
60
+ /*
61
+ * Stored over derived, file over stored.
62
+ *
63
+ * Stored beats derived because a bare template is only a default: making
64
+ * one called `claude` with a model on it is exactly how you say "when I
65
+ * pick claude, I mean this". File beats stored because someone who wrote a
66
+ * template by hand meant it, and a UI silently overriding their file is
67
+ * worse than a UI refusing an id the file has claimed - which is what the
68
+ * hub does on create.
69
+ */
70
+ if (store) {
71
+ for (const t of store.listStoredTemplates()) {
72
+ merged[t.id] = fromStored(t, profiles);
73
+ }
74
+ }
75
+ const file = paths.profiles();
76
+ if (existsSync(file)) {
77
+ try {
78
+ const raw = parseToml(readFileSync(file, 'utf8'));
79
+ // `[template.reviewer]` parses as one table named `template`, which is
80
+ // also why "template" is not usable as an agent id.
81
+ const declared = raw.template;
82
+ if (typeof declared === 'object' && declared !== null) {
83
+ for (const [id, v] of Object.entries(declared)) {
84
+ if (typeof v !== 'object' || v === null)
85
+ continue;
86
+ const t = v;
87
+ const agent = typeof t.agent === 'string' ? t.agent : id;
88
+ merged[id] = {
89
+ id,
90
+ description: typeof t.description === 'string'
91
+ ? t.description
92
+ : (profiles.get(agent)?.description ?? id),
93
+ agent,
94
+ model: typeof t.model === 'string' ? t.model : undefined,
95
+ effort: typeof t.effort === 'string' ? t.effort : undefined,
96
+ prompt: typeof t.prompt === 'string' ? t.prompt : undefined,
97
+ source: 'file',
98
+ };
99
+ }
100
+ }
101
+ }
102
+ catch (err) {
103
+ console.error(`[templates] ignoring ${file}: ${err.message}`);
104
+ }
105
+ }
106
+ for (const t of Object.values(merged)) {
107
+ const problem = validate(t, profiles);
108
+ if (problem)
109
+ t.error = problem;
110
+ }
111
+ return new TemplateRegistry(merged);
112
+ }
113
+ get(id) {
114
+ return this.templates[id] ?? null;
115
+ }
116
+ list() {
117
+ return Object.values(this.templates);
118
+ }
119
+ /** What the browser is given to build the picker from. */
120
+ info() {
121
+ return this.list().map((t) => ({
122
+ id: t.id,
123
+ description: t.description,
124
+ agent: t.agent,
125
+ model: t.model ?? null,
126
+ effort: t.effort ?? null,
127
+ prompt: t.prompt ?? null,
128
+ error: t.error ?? null,
129
+ source: t.source,
130
+ }));
131
+ }
132
+ }
133
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/agents/templates.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { AgentProfile } from './profiles.js';
1
+ import { type AgentProfile } from './profiles.js';
2
2
  /**
3
3
  * Everything an agent process needs on disk before it starts: its MCP config,
4
4
  * its hook settings, and its brief. All generated per launch into
@@ -20,11 +20,40 @@ export interface WiringOutput {
20
20
  mcpConfigPath: string;
21
21
  settingsPath: string;
22
22
  briefPath: string;
23
+ /**
24
+ * Gemini CLI reads no `--mcp-config`; the only per-run way in is
25
+ * GEMINI_CLI_SYSTEM_SETTINGS_PATH, which points its *system* settings layer
26
+ * at a file of our choosing. Written for every wired session rather than
27
+ * only for gemini, so a profile stays a config entry naming a path and not
28
+ * a special case in this file.
29
+ */
30
+ geminiSettingsPath: string;
31
+ /**
32
+ * opencode's whole config, as a JSON string for an environment variable.
33
+ *
34
+ * The odd one out, and the least invasive of the three: opencode reads
35
+ * `OPENCODE_CONFIG_CONTENT` directly, so there is no file at all - not even
36
+ * one of ours. It is merged with the user's own config rather than replacing
37
+ * it, so their models, themes and their own MCP servers survive the session.
38
+ */
39
+ opencodeConfig: string;
23
40
  }
41
+ /**
42
+ * Where a session's brief is written. Exported because an agent with no
43
+ * `--append-system-prompt-file` has its brief typed into the terminal
44
+ * instead, and the hub needs to read back what was written here.
45
+ */
46
+ export declare function briefFileFor(sessionId: string): string;
24
47
  export declare function writeWiring(input: WiringInput): WiringOutput;
25
48
  /**
26
49
  * Without this an agent has no idea why text is appearing in its input, or
27
50
  * that it has an identity and peers at all.
51
+ *
52
+ * An unwired agent gets a shorter one. It is not a courtesy: the router writes
53
+ * to any running window it can resolve an address for, so such an agent can be
54
+ * messaged whether or not it was ever told messaging exists - and the
55
+ * paragraph telling it that a `[from ...]` line is a colleague rather than the
56
+ * human is exactly the paragraph it would otherwise be missing.
28
57
  */
29
58
  export declare function renderBrief(input: WiringInput): string;
30
59
  //# sourceMappingURL=wiring.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"wiring.d.ts","sourceRoot":"","sources":["../../src/agents/wiring.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD;;;;GAIG;AAEH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAOD,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,CAsE5D;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAiDtD"}
1
+ {"version":3,"file":"wiring.d.ts","sourceRoot":"","sources":["../../src/agents/wiring.ts"],"names":[],"mappings":"AAGA,OAAO,EAAa,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7D;;;;GAIG;AAEH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;;;;OAOG;IACH,cAAc,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEtD;AAOD,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,YAAY,CAgD5D;AAwID;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAuEtD"}