@krtclcdy/tersio 2.25.3 → 2.25.5

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 (61) hide show
  1. package/README.md +14 -31
  2. package/dashboard/dist/index.html +18 -16
  3. package/dist/cli/backups.js +194 -0
  4. package/dist/cli/common.js +2 -2
  5. package/dist/cli/dashboard.js +125 -98
  6. package/dist/cli/doctor-fix.js +42 -45
  7. package/dist/cli/doctor.js +70 -8
  8. package/dist/cli/hosts.js +4 -4
  9. package/dist/cli/install.js +106 -38
  10. package/dist/cli/manifest.js +45 -16
  11. package/dist/cli/profile.js +1 -1
  12. package/dist/cli/uninstall.js +21 -5
  13. package/dist/cli/update.js +3 -3
  14. package/dist/cli/usage.js +75 -4
  15. package/dist/extensions/{caveman-session → caveman}/index.js +10 -3
  16. package/dist/extensions/{combo-toggle → combo}/index.js +3 -3
  17. package/dist/extensions/{tersio-commands → commands}/index.js +1 -1
  18. package/dist/extensions/rtk/filter.js +87 -0
  19. package/dist/extensions/{rtk-session/index.js → rtk/session.js} +4 -3
  20. package/dist/extensions/{opencode/server.js → server.js} +52 -8
  21. package/dist/extensions/shared/agent-stats.js +1262 -0
  22. package/dist/extensions/shared/brand-marks.js +154 -0
  23. package/dist/extensions/shared/host.js +18 -12
  24. package/dist/extensions/shared/plugin-settings.js +1 -1
  25. package/dist/extensions/shared/pricing.js +91 -27
  26. package/dist/extensions/shared/session-state.js +3 -1
  27. package/dist/extensions/shared/usage-ledger.js +79 -17
  28. package/dist/extensions/shared/usage-store.js +106 -22
  29. package/dist/extensions/{lib → shared}/utils.js +1 -1
  30. package/dist/extensions/{ai-addons-updater → updater}/index.js +15 -5
  31. package/dist/probe-catalog.js +48 -0
  32. package/dist/probe-catalog188.js +44 -0
  33. package/dist/tersio.js +2 -2
  34. package/extensions/{caveman-session → caveman}/index.ts +10 -3
  35. package/extensions/{combo-toggle → combo}/index.ts +3 -3
  36. package/extensions/{tersio-commands → commands}/index.ts +1 -1
  37. package/extensions/rtk/filter.ts +90 -0
  38. package/extensions/{rtk-session/index.ts → rtk/session.ts} +4 -3
  39. package/extensions/{opencode/server.ts → server.ts} +46 -9
  40. package/extensions/shared/agent-stats.ts +1657 -0
  41. package/extensions/shared/brand-marks.ts +163 -0
  42. package/extensions/shared/host.ts +26 -13
  43. package/extensions/shared/plugin-settings.ts +1 -1
  44. package/extensions/shared/pricing.ts +107 -28
  45. package/extensions/shared/session-state.ts +3 -1
  46. package/extensions/shared/types.ts +10 -2
  47. package/extensions/shared/usage-ledger.ts +94 -19
  48. package/extensions/shared/usage-store.ts +106 -22
  49. package/extensions/{lib → shared}/utils.ts +1 -1
  50. package/extensions/{ai-addons-updater → updater}/index.ts +17 -7
  51. package/package.json +13 -12
  52. package/dist/cli/headroom-install.js +0 -266
  53. package/dist/cli/headroom.js +0 -492
  54. package/dist/extensions/headroom-session/index.js +0 -93
  55. package/dist/extensions/shared/headroom.js +0 -131
  56. /package/dist/extensions/{caveman-session → caveman}/rule-megacave.md +0 -0
  57. /package/dist/extensions/{caveman-session → caveman}/rule-ultra.md +0 -0
  58. /package/dist/extensions/{caveman-session → caveman}/rule.md +0 -0
  59. /package/extensions/{caveman-session → caveman}/rule-megacave.md +0 -0
  60. /package/extensions/{caveman-session → caveman}/rule-ultra.md +0 -0
  61. /package/extensions/{caveman-session → caveman}/rule.md +0 -0
@@ -1,14 +1,15 @@
1
1
  // OpenCode plugin entry: maps its plugin API onto the shared ExtensionApi the mode extensions consume.
2
2
  import { execFile } from 'node:child_process';
3
3
  import type { Plugin } from '@opencode/plugin';
4
- import cavemanSessionExtension from '../caveman-session/index.ts';
5
- import rtkSessionExtension from '../rtk-session/index.ts';
6
- import comboToggleExtension from '../combo-toggle/index.ts';
7
- import tersioCommandsExtension from '../tersio-commands/index.ts';
8
- import { getSharedComboState } from '../shared/session-state.ts';
9
- import { formatStatus } from '../shared/status.ts';
10
- import { resolveRtkBinary } from '../lib/utils.ts';
11
- import type { ExtensionApi, ExtensionCtx, InputEvent, SessionEntry, SystemPromptEvent } from '../shared/types.ts';
4
+ import cavemanSessionExtension from './caveman/index.ts';
5
+ import rtkSessionExtension from './rtk/session.ts';
6
+ import rtkFilterExtension, { FILTER_BY_TOOL, MIN_FILTER_BYTES, filterThroughRtk, filterableText, rtkActive } from './rtk/filter.ts';
7
+ import comboToggleExtension from './combo/index.ts';
8
+ import tersioCommandsExtension from './commands/index.ts';
9
+ import { getSharedComboState } from './shared/session-state.ts';
10
+ import { formatStatus } from './shared/status.ts';
11
+ import { resolveRtkBinary } from './shared/utils.ts';
12
+ import type { ExtensionApi, ExtensionCtx, InputEvent, SessionEntry, SystemPromptEvent } from './shared/types.ts';
12
13
 
13
14
  interface CommandConfig {
14
15
  description: string;
@@ -54,6 +55,7 @@ const plugin: Plugin.Plugin = {
54
55
  return list;
55
56
  };
56
57
  const persist = (sid: string): void => {
58
+ // SAFETY: the storage API is generic over its payload; the value round-trips unchanged.
57
59
  void ctx.storage.set(`entries:${sid}`, sessionEntriesOf(sid) as unknown as never).catch(() => {});
58
60
  };
59
61
  const stubCtx = (sid?: string): ExtensionCtx => ({
@@ -120,7 +122,7 @@ const plugin: Plugin.Plugin = {
120
122
  },
121
123
  };
122
124
 
123
- for (const extension of [cavemanSessionExtension, rtkSessionExtension, comboToggleExtension, tersioCommandsExtension]) extension(host);
125
+ for (const extension of [cavemanSessionExtension, rtkSessionExtension, rtkFilterExtension, comboToggleExtension, tersioCommandsExtension]) extension(host);
124
126
 
125
127
  // The first hook of an unseen session runs its session_start handlers.
126
128
  const sidOf = (value: unknown): string | undefined =>
@@ -206,9 +208,44 @@ const plugin: Plugin.Plugin = {
206
208
  const rewritten = await rewriteCommand(input.command);
207
209
  if (rewritten) input.command = rewritten;
208
210
  });
211
+
212
+ // Built-in grep and glob output never reaches the bash hook; mutate result.content in place.
213
+ try {
214
+ await ctx.tool.hook('execute.after', async (event) => {
215
+ const hook = event as { tool?: unknown; status?: unknown; sessionID?: unknown; result?: { content?: unknown } };
216
+ if (hook.status !== 'completed') return;
217
+ const filter = FILTER_BY_TOOL.get(String(hook.tool ?? '').toLowerCase());
218
+ if (!filter || !hook.result) return;
219
+ const text = filterableText(hook.result.content);
220
+ if (text === null || text.length < MIN_FILTER_BYTES) return;
221
+ // Read the mode from the payload's own session, not the last one to run a start hook.
222
+ const sid = typeof hook.sessionID === 'string' ? hook.sessionID : activeSid;
223
+ if (sid !== undefined) await ensureSession(sid);
224
+ if (!rtkActive(sid === undefined ? undefined : sessionEntriesOf(sid))) return;
225
+ const bin = resolveRtkBinary();
226
+ if (!bin) return;
227
+ const filtered = await filterThroughRtk(execRtk, { bin, filter, text });
228
+ if (filtered) hook.result.content = [{ type: 'text', text: filtered }];
229
+ });
230
+ } catch {
231
+ // Hosts without the after-hook keep the unfiltered result.
232
+ }
209
233
  },
210
234
  };
211
235
 
236
+ /** execFile with the promise shape `filterThroughRtk` expects. */
237
+ function execRtk(cmd: string, args: string[], opts?: { signal?: AbortSignal; timeout?: number }): Promise<{ stdout: string; code: number }> {
238
+ return new Promise((resolve) => {
239
+ execFile(cmd, args, { signal: opts?.signal, timeout: opts?.timeout }, (error, stdout) => {
240
+ const out = stdout ?? '';
241
+ if (!error) return resolve({ stdout: out, code: 0 });
242
+ // A non-numeric code is a spawn failure (ENOENT, EACCES, killed) and must not read as success.
243
+ const raw = (error as { code?: unknown }).code;
244
+ resolve({ stdout: out, code: typeof raw === 'number' ? raw : 1 });
245
+ });
246
+ });
247
+ }
248
+
212
249
  function rewriteCommand(command: string): Promise<string | null> {
213
250
  const bin = resolveRtkBinary();
214
251
  if (!bin) return Promise.resolve(null);