@typescript-agent-harness/cli 0.29.1 → 0.30.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 (72) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/env.d.ts +1 -1
  4. package/dist/env.d.ts.map +1 -1
  5. package/dist/env.js +4 -2
  6. package/dist/env.js.map +1 -1
  7. package/dist/host.d.ts +2 -0
  8. package/dist/host.d.ts.map +1 -1
  9. package/dist/host.js +13 -6
  10. package/dist/host.js.map +1 -1
  11. package/dist/index.d.ts +1 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/prompt.d.ts +2 -0
  15. package/dist/prompt.d.ts.map +1 -1
  16. package/dist/prompt.js +8 -0
  17. package/dist/prompt.js.map +1 -1
  18. package/dist/runtime.d.ts +3 -0
  19. package/dist/runtime.d.ts.map +1 -1
  20. package/dist/runtime.js +44 -16
  21. package/dist/runtime.js.map +1 -1
  22. package/dist/serve/choose.d.ts +17 -0
  23. package/dist/serve/choose.d.ts.map +1 -0
  24. package/dist/serve/choose.js +48 -0
  25. package/dist/serve/choose.js.map +1 -0
  26. package/dist/serve/fs.d.ts +5 -0
  27. package/dist/serve/fs.d.ts.map +1 -0
  28. package/dist/serve/fs.js +47 -0
  29. package/dist/serve/fs.js.map +1 -0
  30. package/dist/serve/http.d.ts +6 -2
  31. package/dist/serve/http.d.ts.map +1 -1
  32. package/dist/serve/http.js +149 -21
  33. package/dist/serve/http.js.map +1 -1
  34. package/dist/serve/hub.d.ts +3 -1
  35. package/dist/serve/hub.d.ts.map +1 -1
  36. package/dist/serve/hub.js +24 -3
  37. package/dist/serve/hub.js.map +1 -1
  38. package/dist/serve/protocol.d.ts +94 -1
  39. package/dist/serve/protocol.d.ts.map +1 -1
  40. package/dist/serve/run.d.ts +4 -1
  41. package/dist/serve/run.d.ts.map +1 -1
  42. package/dist/serve/run.js +38 -21
  43. package/dist/serve/run.js.map +1 -1
  44. package/dist/serve/workspaces.d.ts +32 -0
  45. package/dist/serve/workspaces.d.ts.map +1 -0
  46. package/dist/serve/workspaces.js +137 -0
  47. package/dist/serve/workspaces.js.map +1 -0
  48. package/dist/settings.d.ts +26 -0
  49. package/dist/settings.d.ts.map +1 -0
  50. package/dist/settings.js +69 -0
  51. package/dist/settings.js.map +1 -0
  52. package/dist/skills/discover.d.ts +0 -1
  53. package/dist/skills/discover.d.ts.map +1 -1
  54. package/dist/skills/discover.js +5 -6
  55. package/dist/skills/discover.js.map +1 -1
  56. package/dist/skills/install.d.ts +12 -0
  57. package/dist/skills/install.d.ts.map +1 -0
  58. package/dist/skills/install.js +60 -0
  59. package/dist/skills/install.js.map +1 -0
  60. package/dist/watch.d.ts +2 -0
  61. package/dist/watch.d.ts.map +1 -1
  62. package/dist/watch.js +5 -3
  63. package/dist/watch.js.map +1 -1
  64. package/dist/web/assets/index-WRCh4A0t.css +1 -0
  65. package/dist/web/assets/{index-By2PRbDq.js → index-gOZCYfzp.js} +4 -4
  66. package/dist/web/index.html +2 -2
  67. package/dist/workspaces.d.ts +8 -0
  68. package/dist/workspaces.d.ts.map +1 -0
  69. package/dist/workspaces.js +53 -0
  70. package/dist/workspaces.js.map +1 -0
  71. package/package.json +9 -9
  72. package/dist/web/assets/index-CW-h-0xR.css +0 -1
@@ -4,8 +4,8 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>tah</title>
7
- <script type="module" crossorigin src="/assets/index-By2PRbDq.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-CW-h-0xR.css">
7
+ <script type="module" crossorigin src="/assets/index-gOZCYfzp.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-WRCh4A0t.css">
9
9
  </head>
10
10
  <body>
11
11
  <div id="root"></div>
@@ -0,0 +1,8 @@
1
+ /** Folders shown in the `tah serve` sidebar, under `<home>/.tah/workspaces.json`. */
2
+ export declare function workspacesPath(home: string): string;
3
+ export declare function loadWorkspaces(home: string): string[];
4
+ /** Folders removed from the sidebar, newest first. */
5
+ export declare function loadRecent(home: string): string[];
6
+ export declare function addWorkspace(home: string, dir: string): string[];
7
+ export declare function removeWorkspace(home: string, dir: string): string[];
8
+ //# sourceMappingURL=workspaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.d.ts","sourceRoot":"","sources":["../src/workspaces.ts"],"names":[],"mappings":"AAOA,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAuBD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAErD;AAED,sDAAsD;AACtD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAEjD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAQhE;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAOnE"}
@@ -0,0 +1,53 @@
1
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ const RECENT_MAX = 10;
4
+ /** Folders shown in the `tah serve` sidebar, under `<home>/.tah/workspaces.json`. */
5
+ export function workspacesPath(home) {
6
+ return path.join(home, ".tah", "workspaces.json");
7
+ }
8
+ function load(home) {
9
+ const file = workspacesPath(home);
10
+ if (!existsSync(file))
11
+ return { workspaces: [], recent: [] };
12
+ try {
13
+ const raw = JSON.parse(readFileSync(file, "utf8"));
14
+ const dirs = (v) => Array.isArray(v) ? [...new Set(v.filter((d) => typeof d === "string").map((d) => path.resolve(d)))] : [];
15
+ return { workspaces: dirs(raw?.workspaces), recent: dirs(raw?.recent) };
16
+ }
17
+ catch {
18
+ // unreadable file: treat as no folders
19
+ return { workspaces: [], recent: [] };
20
+ }
21
+ }
22
+ function save(home, stored) {
23
+ const file = workspacesPath(home);
24
+ mkdirSync(path.dirname(file), { recursive: true });
25
+ writeFileSync(file, `${JSON.stringify(stored, null, 2)}\n`);
26
+ return stored;
27
+ }
28
+ export function loadWorkspaces(home) {
29
+ return load(home).workspaces;
30
+ }
31
+ /** Folders removed from the sidebar, newest first. */
32
+ export function loadRecent(home) {
33
+ return load(home).recent;
34
+ }
35
+ export function addWorkspace(home, dir) {
36
+ const stored = load(home);
37
+ const target = path.resolve(dir);
38
+ if (stored.workspaces.includes(target) && !stored.recent.includes(target))
39
+ return stored.workspaces;
40
+ return save(home, {
41
+ workspaces: stored.workspaces.includes(target) ? stored.workspaces : [...stored.workspaces, target],
42
+ recent: stored.recent.filter((d) => d !== target),
43
+ }).workspaces;
44
+ }
45
+ export function removeWorkspace(home, dir) {
46
+ const stored = load(home);
47
+ const target = path.resolve(dir);
48
+ return save(home, {
49
+ workspaces: stored.workspaces.filter((d) => d !== target),
50
+ recent: [target, ...stored.recent.filter((d) => d !== target)].slice(0, RECENT_MAX),
51
+ }).workspaces;
52
+ }
53
+ //# sourceMappingURL=workspaces.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspaces.js","sourceRoot":"","sources":["../src/workspaces.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typescript-agent-harness/cli",
3
- "version": "0.29.1",
3
+ "version": "0.30.1",
4
4
  "description": "typescript-agent-harness CLI (tah)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,14 +27,14 @@
27
27
  "marked-terminal": "^7.3.0",
28
28
  "react": "^19.3.0",
29
29
  "string-width": "^8.3.0",
30
- "@typescript-agent-harness/core": "0.29.1",
31
- "@typescript-agent-harness/llm": "0.29.1",
32
- "@typescript-agent-harness/permissions": "0.29.1",
33
- "@typescript-agent-harness/scheduler": "0.29.1",
34
- "@typescript-agent-harness/tools": "0.29.1",
35
- "@typescript-agent-harness/storage": "0.29.1",
36
- "@typescript-agent-harness/agent": "0.29.1",
37
- "@typescript-agent-harness/mcp": "0.29.1"
30
+ "@typescript-agent-harness/llm": "0.30.1",
31
+ "@typescript-agent-harness/mcp": "0.30.1",
32
+ "@typescript-agent-harness/agent": "0.30.1",
33
+ "@typescript-agent-harness/core": "0.30.1",
34
+ "@typescript-agent-harness/permissions": "0.30.1",
35
+ "@typescript-agent-harness/scheduler": "0.30.1",
36
+ "@typescript-agent-harness/tools": "0.30.1",
37
+ "@typescript-agent-harness/storage": "0.30.1"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@types/node": "^22.18.0",
@@ -1 +0,0 @@
1
- :root{--bg:#fff;--panel:#f6f7f9;--border:#e3e5e8;--text:#1f2328;--muted:#6b7280;--accent:#0e7490;--accent-text:#fff;--ok:#15803d;--fail:#b91c1c;--warn:#b45309;--code-bg:#f3f4f6;--hl-keyword:#cf222e;--hl-string:#0a3069;--hl-comment:#6e7781;--hl-number:#0550ae;--hl-title:#8250df;--hl-attr:#953800;--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light dark;color:var(--text);background:var(--bg);font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,PingFang SC,Microsoft YaHei,sans-serif;font-size:15px;line-height:1.6}@media (prefers-color-scheme:dark){:root{--lightningcss-light: ;--lightningcss-dark:initial;--bg:#0f1115;--panel:#161a20;--border:#2a2f37;--text:#e6e6e6;--muted:#9aa1ab;--accent:#22a6c4;--accent-text:#0f1115;--ok:#4ade80;--fail:#f87171;--warn:#fbbf24;--code-bg:#1c2028;--hl-keyword:#ff7b72;--hl-string:#a5d6ff;--hl-comment:#8b949e;--hl-number:#79c0ff;--hl-title:#d2a8ff;--hl-attr:#ffa657}}*{box-sizing:border-box}html,body,#root{height:100%;margin:0}button{font:inherit;color:var(--text);background:var(--panel);border:1px solid var(--border);cursor:pointer;border-radius:6px;padding:4px 12px}button:disabled{opacity:.5;cursor:default}button.primary{background:var(--accent);border-color:var(--accent);color:var(--accent-text)}button.danger{color:var(--fail)}code,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px}.app{height:100%;display:flex}.sidebar{border-right:1px solid var(--border);background:var(--panel);flex-direction:column;flex-shrink:0;width:260px;display:flex}.sidebar-actions{gap:8px;padding:12px;display:flex}.sidebar-note{color:var(--muted);padding:0 12px 8px;font-size:13px}.sessions{padding:0 8px 12px;overflow-y:auto}.sessions ul{margin:0;padding:0;list-style:none}.sessions-heading{color:var(--muted);padding:8px 8px 4px;font-size:12px}.session-item{border-radius:6px;margin-bottom:2px}.session-item:hover{background:var(--bg)}.session-item.current{background:var(--bg);box-shadow:inset 2px 0 0 var(--accent)}.session{align-items:center;gap:4px;width:100%;padding:2px 4px 2px 8px;display:flex}.session-pick{text-align:left;min-width:0;color:inherit;font:inherit;background:0 0;border:none;flex:1;padding:2px 0;display:flex}.session .preview{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.session-time{color:var(--muted);flex:none;font-size:12px}.session-tools{flex:none;gap:2px;display:none}.session-item:hover .session-time{display:none}.session-item:hover .session-tools{display:flex}.session-tools button{color:var(--muted);background:0 0;border:none;border-radius:4px;padding:3px;display:flex}.session-tools button:hover,.session-tools button.on{color:var(--text)}.session-tools button:hover{background:var(--panel)}.context-menu{z-index:10;border:1px solid var(--border);background:var(--bg);border-radius:8px;min-width:160px;margin:0;padding:4px;list-style:none;position:fixed;box-shadow:0 6px 20px #00000026}.context-menu button{text-align:left;background:0 0;border:none;width:100%;padding:4px 10px;font-size:14px}.context-menu button:not(:disabled):hover{background:var(--panel)}.session-rename{border:1px solid var(--border);width:100%;font:inherit;background:var(--panel);color:var(--fg);border-radius:4px;padding:4px 6px}.user-attach-fallback{color:var(--muted);font-size:13px}main{flex-direction:column;flex:1;min-width:0;display:flex}.banner{color:var(--warn);border-bottom:1px solid var(--border);padding:6px 16px;font-size:13px}.messages{flex:1;padding:16px max(16px,50% - 430px);overflow-y:auto}.empty{text-align:center;flex-direction:column;justify-content:center;align-items:center;min-height:min(52vh,420px);padding:24px 16px;display:flex}.empty-title{letter-spacing:-.02em;color:var(--text);font-size:1.25rem;font-weight:600}.empty-hint{max-width:28rem;color:var(--muted);margin:8px 0 0;font-size:14px}.user{background:var(--panel);white-space:pre-wrap;word-break:break-word;border-radius:8px;margin:20px 0 8px;padding:8px 12px}.user-attach{flex-wrap:wrap;gap:6px;margin-bottom:6px;display:flex}.user-attach-chip{background:var(--bg);border:1px solid var(--border);color:var(--muted);white-space:nowrap;border-radius:999px;padding:2px 8px;font-size:12px}.reply{word-break:break-word}.reply pre{background:var(--code-bg);border-radius:6px;padding:10px 12px;overflow-x:auto}.reply :not(pre)>code{background:var(--code-bg);border-radius:4px;padding:1px 4px}.reply table{border-collapse:collapse}.reply th,.reply td{border:1px solid var(--border);padding:4px 8px}.hljs-keyword,.hljs-selector-tag,.hljs-literal{color:var(--hl-keyword)}.hljs-string,.hljs-regexp{color:var(--hl-string)}.hljs-comment,.hljs-quote{color:var(--hl-comment);font-style:italic}.hljs-number,.hljs-variable{color:var(--hl-number)}.hljs-title,.hljs-section,.hljs-function{color:var(--hl-title)}.hljs-attr,.hljs-attribute,.hljs-built_in,.hljs-type{color:var(--hl-attr)}.tool{white-space:nowrap;align-items:center;gap:8px;margin:4px 0;font-size:14px;display:flex;overflow:hidden}.tool .dot{color:var(--accent)}.tool.failed .dot,.tool.failed .result{color:var(--fail)}.tool .name{font-weight:600}.tool .summary{color:var(--muted);text-overflow:ellipsis;overflow:hidden}.tool.ok .result{color:var(--ok)}.notice{color:var(--muted);margin:4px 0;font-size:13px}.notice.error{color:var(--fail)}.thinking{color:var(--muted);align-items:center;gap:8px;margin:8px 0;display:flex}.spinner{border:2px solid var(--border);border-top-color:var(--accent);border-radius:50%;width:12px;height:12px;animation:.8s linear infinite spin;display:inline-block}@keyframes spin{to{transform:rotate(360deg)}}.card{border:1px solid var(--warn);border-radius:8px;margin:12px 0;padding:12px}.card-title{margin-bottom:8px;font-weight:600}.card-body{background:var(--code-bg);white-space:pre-wrap;border-radius:6px;max-height:240px;margin:0 0 12px;padding:8px;overflow:auto}.card-actions{gap:8px;display:flex}.composer-wrap{padding:8px max(16px,50% - 430px)}.attach-rail{gap:8px;padding-bottom:8px;display:flex;overflow-x:auto}.attach-card{border:1px solid var(--border);background:var(--panel);border-radius:12px;flex:none;align-items:center;gap:8px;min-width:180px;max-width:240px;height:64px;padding:6px 8px;display:flex;position:relative}.attach-card img{object-fit:cover;border-radius:6px;width:48px;height:48px}.attach-ext{width:48px;height:48px;color:var(--muted);background:var(--bg);border-radius:6px;place-items:center;font-size:11px;font-weight:600;display:grid}.attach-meta{flex:1;min-width:0}.attach-name{text-overflow:ellipsis;white-space:nowrap;font-size:13px;overflow:hidden}.attach-sub{color:var(--muted);font-size:11px}.attach-card.error .attach-sub{color:var(--fail)}.attach-remove{width:22px;line-height:1;position:absolute;top:2px;right:2px;border-radius:11px!important;height:22px!important;padding:0!important}.composer{align-items:flex-end;gap:8px;display:flex}.composer textarea{resize:none;font:inherit;color:var(--text);background:var(--bg);border:1px solid var(--border);border-radius:8px;outline:none;flex:1;min-height:42px;padding:8px 12px}.composer textarea:focus{border-color:var(--accent)}.composer button{border-radius:8px;height:42px;padding:0 16px}.composer .attach-btn{width:42px;padding:0;font-size:20px;line-height:1}.status{color:var(--muted);padding:4px max(16px,50% - 430px) 10px;font-size:12px}.signed-out{text-align:center;max-width:480px;color:var(--muted);margin:20vh auto}