@danieltmn/tamnora 0.1.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 (123) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/LICENSE +21 -0
  3. package/README.md +130 -0
  4. package/SECURITY.md +31 -0
  5. package/harness/packages/cli/bin/tamnora.mjs +11 -0
  6. package/harness/packages/cli/package.json +10 -0
  7. package/harness/packages/cli/src/cli.js +90 -0
  8. package/harness/packages/cli/src/commands/autostart.js +121 -0
  9. package/harness/packages/cli/src/commands/bridge.js +274 -0
  10. package/harness/packages/cli/src/commands/doctor.js +73 -0
  11. package/harness/packages/cli/src/commands/eval.js +183 -0
  12. package/harness/packages/cli/src/commands/init.js +31 -0
  13. package/harness/packages/cli/src/commands/mcp.js +101 -0
  14. package/harness/packages/cli/src/commands/repl.js +172 -0
  15. package/harness/packages/cli/src/commands/run.js +165 -0
  16. package/harness/packages/cli/src/commands/serve.js +1 -0
  17. package/harness/packages/cli/src/commands/server.js +345 -0
  18. package/harness/packages/cli/src/commands/tui.js +110 -0
  19. package/harness/packages/cli/src/commands/update.js +76 -0
  20. package/harness/packages/cli/src/commands/user.js +135 -0
  21. package/harness/packages/cli/src/lib/core.js +2 -0
  22. package/harness/packages/cli/src/lib/daemon.js +153 -0
  23. package/harness/packages/cli/src/lib/qr.js +203 -0
  24. package/harness/packages/cli/src/lib/runtime.js +110 -0
  25. package/harness/packages/cli/src/lib/tunnel.js +113 -0
  26. package/harness/packages/cli/src/lib/util.js +24 -0
  27. package/harness/packages/cli/src/tui/app.js +302 -0
  28. package/harness/packages/cli/src/tui/keys.js +78 -0
  29. package/harness/packages/cli/src/tui/layout.js +130 -0
  30. package/harness/packages/cli/src/tui/screen.js +13 -0
  31. package/harness/packages/cli/src/ui/color.js +15 -0
  32. package/harness/packages/cli/test/release.test.js +34 -0
  33. package/harness/packages/cli/test/tui.test.js +99 -0
  34. package/harness/packages/cli/test/tunnel.test.js +20 -0
  35. package/harness/packages/core/package.json +14 -0
  36. package/harness/packages/core/src/agent/context.js +66 -0
  37. package/harness/packages/core/src/agent/modes.js +26 -0
  38. package/harness/packages/core/src/agent/runAgent.js +257 -0
  39. package/harness/packages/core/src/config/app.js +49 -0
  40. package/harness/packages/core/src/config/home.js +98 -0
  41. package/harness/packages/core/src/config/identity.js +41 -0
  42. package/harness/packages/core/src/config/index.js +69 -0
  43. package/harness/packages/core/src/config/providers.js +24 -0
  44. package/harness/packages/core/src/env.js +19 -0
  45. package/harness/packages/core/src/eval/dataset.js +47 -0
  46. package/harness/packages/core/src/eval/judge.js +39 -0
  47. package/harness/packages/core/src/eval/report.js +48 -0
  48. package/harness/packages/core/src/eval/runTask.js +71 -0
  49. package/harness/packages/core/src/eval/runner.js +150 -0
  50. package/harness/packages/core/src/eval/scorers.js +217 -0
  51. package/harness/packages/core/src/eval/task.js +59 -0
  52. package/harness/packages/core/src/index.js +72 -0
  53. package/harness/packages/core/src/mcp/common.js +82 -0
  54. package/harness/packages/core/src/mcp/http.js +149 -0
  55. package/harness/packages/core/src/mcp/index.js +167 -0
  56. package/harness/packages/core/src/mcp/stdio.js +218 -0
  57. package/harness/packages/core/src/providers/index.js +119 -0
  58. package/harness/packages/core/src/providers/ollama.js +76 -0
  59. package/harness/packages/core/src/providers/openaiCompatible.js +57 -0
  60. package/harness/packages/core/src/providers/openrouter.js +57 -0
  61. package/harness/packages/core/src/providers/presets.js +19 -0
  62. package/harness/packages/core/src/providers/resilience.js +74 -0
  63. package/harness/packages/core/src/providers/stream.js +200 -0
  64. package/harness/packages/core/src/providers/utils.js +66 -0
  65. package/harness/packages/core/src/storage/sqlite.js +453 -0
  66. package/harness/packages/core/src/tools/diff.js +90 -0
  67. package/harness/packages/core/src/tools/executors.js +277 -0
  68. package/harness/packages/core/src/tools/glob.js +67 -0
  69. package/harness/packages/core/src/tools/index.js +28 -0
  70. package/harness/packages/core/src/tools/paths.js +29 -0
  71. package/harness/packages/core/src/tools/permissions.js +69 -0
  72. package/harness/packages/core/src/tools/registry.js +44 -0
  73. package/harness/packages/core/src/tools/schema.js +177 -0
  74. package/harness/packages/core/test/agent.test.js +237 -0
  75. package/harness/packages/core/test/config.test.js +33 -0
  76. package/harness/packages/core/test/context.test.js +44 -0
  77. package/harness/packages/core/test/diff.test.js +20 -0
  78. package/harness/packages/core/test/eval.test.js +144 -0
  79. package/harness/packages/core/test/git-tools.test.js +44 -0
  80. package/harness/packages/core/test/home.test.js +62 -0
  81. package/harness/packages/core/test/mcp.test.js +158 -0
  82. package/harness/packages/core/test/providers.test.js +80 -0
  83. package/harness/packages/core/test/resilience.test.js +61 -0
  84. package/harness/packages/core/test/storage.test.js +55 -0
  85. package/harness/packages/core/test/stream.test.js +91 -0
  86. package/harness/packages/core/test/tools.test.js +96 -0
  87. package/harness/packages/server/bin/tamnora-server.mjs +11 -0
  88. package/harness/packages/server/package.json +10 -0
  89. package/harness/packages/server/public/app.js +2188 -0
  90. package/harness/packages/server/public/img/fondo-agentes.webp +0 -0
  91. package/harness/packages/server/public/index.html +368 -0
  92. package/harness/packages/server/public/landing/index.html +523 -0
  93. package/harness/packages/server/public/landing/landing.js +89 -0
  94. package/harness/packages/server/public/markdown.js +174 -0
  95. package/harness/packages/server/public/styles.css +923 -0
  96. package/harness/packages/server/src/auth.js +146 -0
  97. package/harness/packages/server/src/cli.js +61 -0
  98. package/harness/packages/server/src/index.js +1 -0
  99. package/harness/packages/server/src/lib/approvals.js +51 -0
  100. package/harness/packages/server/src/lib/core.js +2 -0
  101. package/harness/packages/server/src/lib/http.js +74 -0
  102. package/harness/packages/server/src/lib/modelCache.js +32 -0
  103. package/harness/packages/server/src/lib/prompt.js +48 -0
  104. package/harness/packages/server/src/lib/workspace.js +74 -0
  105. package/harness/packages/server/src/routes/auth.js +56 -0
  106. package/harness/packages/server/src/routes/chat.js +222 -0
  107. package/harness/packages/server/src/routes/eval.js +100 -0
  108. package/harness/packages/server/src/routes/files.js +117 -0
  109. package/harness/packages/server/src/routes/folders.js +80 -0
  110. package/harness/packages/server/src/routes/mcp.js +50 -0
  111. package/harness/packages/server/src/routes/models.js +26 -0
  112. package/harness/packages/server/src/routes/providers.js +135 -0
  113. package/harness/packages/server/src/routes/sessions.js +157 -0
  114. package/harness/packages/server/src/server.js +249 -0
  115. package/harness/packages/server/src/static.js +67 -0
  116. package/harness/packages/server/test/markdown.test.js +36 -0
  117. package/harness/packages/server/test/modelCache.test.js +72 -0
  118. package/harness/packages/server/test/server.test.js +809 -0
  119. package/harness/scripts/example-dataset.jsonl +4 -0
  120. package/harness/scripts/mcp-echo-server.mjs +108 -0
  121. package/harness/scripts/mock-provider.mjs +134 -0
  122. package/harness/tamnora.example.json +18 -0
  123. package/package.json +70 -0
@@ -0,0 +1,368 @@
1
+ <!doctype html>
2
+ <html lang="es">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Tamnora Console</title>
7
+ <script>
8
+ (function () {
9
+ var theme = null;
10
+ try {
11
+ theme = localStorage.getItem('tamnora-console-theme');
12
+ } catch {
13
+ theme = null;
14
+ }
15
+ if (theme === 'light') theme = 'paper';
16
+ document.documentElement.dataset.theme = theme === 'dark' ? 'dark' : 'paper';
17
+ })();
18
+ (function () {
19
+ // La consola resuelve el acceso con /api/auth/me; mientras tanto, oculta.
20
+ var style = document.createElement('style');
21
+ style.textContent = "html[data-auth='pending'] body { visibility: hidden }";
22
+ document.head.appendChild(style);
23
+ document.documentElement.dataset.auth = 'pending';
24
+ })();
25
+ </script>
26
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
27
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
28
+ <link
29
+ rel="stylesheet"
30
+ href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&family=Libre+Baskerville:wght@400;700&family=Manrope:wght@400;500;600;700&display=swap"
31
+ />
32
+ <link rel="stylesheet" href="/styles.css" />
33
+ </head>
34
+ <body>
35
+ <header class="topbar">
36
+ <div class="brand"><span class="logo">T</span> tamnora <span class="ver">v0.0.0</span></div>
37
+ <nav class="tabs">
38
+ <button class="tab active" data-tab="chat">chat</button>
39
+ <button class="tab" data-tab="providers">proveedores</button>
40
+ <div class="menu">
41
+ <button id="more-tab" class="tab" title="más" aria-haspopup="true" aria-expanded="false" aria-label="más">
42
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
43
+ <circle cx="12" cy="12" r="1" />
44
+ <circle cx="19" cy="12" r="1" />
45
+ <circle cx="5" cy="12" r="1" />
46
+ </svg>
47
+ </button>
48
+ <div id="more-menu" class="menu-pop" hidden>
49
+ <button type="button" data-tab="eval">eval</button>
50
+ <button type="button" data-tab="runs">runs</button>
51
+ </div>
52
+ </div>
53
+ </nav>
54
+ <div class="settings">
55
+ <button id="search-toggle" type="button" class="btn icon" title="buscar (Ctrl/Cmd+K)" aria-label="buscar">
56
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
57
+ <circle cx="11" cy="11" r="8" />
58
+ <path d="m21 21-4.3-4.3" />
59
+ </svg>
60
+ </button>
61
+ <button id="settings-toggle" type="button" class="btn icon" title="modelo, modo y auto" aria-label="ajustes del agente">
62
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
63
+ <path d="M21 4h-7M10 4H3M21 12h-9M8 12H3M21 20h-5M12 20H3" />
64
+ <path d="M14 2v4M8 10v4M16 18v4" />
65
+ </svg>
66
+ </button>
67
+ <button id="sidebar-toggle" type="button" class="btn icon" title="mostrar/ocultar sesiones" aria-label="mostrar u ocultar el panel de sesiones" aria-pressed="true">
68
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
69
+ <rect width="18" height="18" x="3" y="3" rx="2" />
70
+ <path d="M9 3v18" />
71
+ </svg>
72
+ </button>
73
+ <button id="explorer-toggle" type="button" class="btn icon" title="mostrar/ocultar archivos" aria-label="mostrar u ocultar el panel de archivos" aria-pressed="false">
74
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
75
+ <rect width="18" height="18" x="3" y="3" rx="2" />
76
+ <path d="M15 3v18" />
77
+ </svg>
78
+ </button>
79
+ <button id="theme-toggle" type="button" class="btn icon" title="cambiar tema" aria-label="cambiar tema">
80
+ <svg class="ico-sun" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
81
+ <circle cx="12" cy="12" r="4" />
82
+ <path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41" />
83
+ </svg>
84
+ <svg class="ico-moon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
85
+ <path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" />
86
+ </svg>
87
+ </button>
88
+ </div>
89
+ </header>
90
+
91
+ <main>
92
+ <section id="view-chat" class="view active">
93
+ <aside id="sidebar" class="sidebar">
94
+ <button id="new-session" class="btn block">+ nueva sesión</button>
95
+ <ul id="sessions" class="sessions"></ul>
96
+ <div class="rail-footer">
97
+ <span>workspace</span>
98
+ <b id="rail-cwd">…</b>
99
+ <a href="/landing" id="logout" class="rail-exit" title="cerrar la sesión visual">salir →</a>
100
+ </div>
101
+ </aside>
102
+ <div id="resizer-sidebar" class="resizer" title="ajustar" role="separator" aria-orientation="vertical"></div>
103
+ <div id="sidebar-backdrop" class="drawer-backdrop" hidden></div>
104
+ <div class="conversation">
105
+ <div id="tabbar" class="tabbar" hidden></div>
106
+ <div id="panes" class="panes">
107
+ <div id="messages" class="messages">
108
+ <div class="empty">
109
+ <div class="empty-brand"><span>Tamnora</span><span class="accent">Harness</span></div>
110
+ <p class="empty-sub">Elegí un proveedor y un modelo, y escribí tu primer mensaje.</p>
111
+ <div class="empty-hints">
112
+ <span class="hint"><kbd>/help</kbd> ver los comandos</span>
113
+ <span class="hint"><kbd>/new</kbd> abrir una sesión en otra carpeta</span>
114
+ <span class="hint"><kbd>/init</kbd> analizar el proyecto y crear AGENTS.md</span>
115
+ </div>
116
+ </div>
117
+ </div>
118
+ </div>
119
+ <form id="chat-form" class="composer">
120
+ <div id="attach-preview" class="attach-preview" hidden></div>
121
+ <div class="composer-row">
122
+ <span class="prompt-mark">❯</span>
123
+ <button type="button" id="attach-image" class="btn icon" title="Adjuntar imagen (o pegala / arrastrala)" aria-label="adjuntar imagen">
124
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
125
+ <rect width="18" height="18" x="3" y="3" rx="2" ry="2" />
126
+ <circle cx="9" cy="9" r="2" />
127
+ <path d="m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" />
128
+ </svg>
129
+ </button>
130
+ <input id="image-input" type="file" accept="image/*" multiple hidden />
131
+ <textarea id="chat-input" rows="1" placeholder="escribí un mensaje…" title="Enter envía · Shift+Enter salto" spellcheck="false"></textarea>
132
+ <button class="btn primary" type="submit">enviar</button>
133
+ <button class="btn" type="button" id="stop-btn" title="Detener la respuesta" hidden>parar</button>
134
+ </div>
135
+ </form>
136
+ <div class="statusbar">
137
+ <span id="sb-mode">agent</span>
138
+ <span class="dot">·</span>
139
+ <span id="sb-provider">—</span>
140
+ <span class="dot">·</span>
141
+ <span id="sb-model">—</span>
142
+ <span class="dot">·</span>
143
+ <span id="sb-rounds">listo</span>
144
+ <span class="spacer"></span>
145
+ <span id="sb-tokens" class="muted">tokens —</span>
146
+ </div>
147
+ </div>
148
+
149
+ <div id="resizer-explorer" class="resizer" title="ajustar" role="separator" aria-orientation="vertical"></div>
150
+
151
+ <aside id="explorer" class="explorer" hidden>
152
+ <div class="explorer-head">
153
+ <span class="explorer-title">estructura</span>
154
+ <span class="spacer"></span>
155
+ <button id="explorer-refresh" type="button" class="btn icon" title="refrescar" aria-label="refrescar">
156
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
157
+ <path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" />
158
+ <path d="M21 3v5h-5" />
159
+ <path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" />
160
+ <path d="M8 16H3v5" />
161
+ </svg>
162
+ </button>
163
+ <button id="explorer-close" type="button" class="btn icon" title="cerrar" aria-label="cerrar el panel de archivos">
164
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
165
+ <path d="M18 6 6 18M6 6l12 12" />
166
+ </svg>
167
+ </button>
168
+ </div>
169
+ <div id="explorer-root" class="explorer-cwd" title=""></div>
170
+ <div class="explorer-filter">
171
+ <input id="explorer-filter" placeholder="filtrar por nombre…" spellcheck="false" />
172
+ </div>
173
+ <ul id="explorer-tree" class="tree"></ul>
174
+ <div id="explorer-status" class="explorer-status"></div>
175
+ </aside>
176
+
177
+ <dialog id="file-modal" class="modal file-modal">
178
+ <div class="modal-card">
179
+ <div class="row between">
180
+ <h3 id="file-title">archivo</h3>
181
+ <div class="file-actions">
182
+ <span id="file-meta" class="muted"></span>
183
+ <button id="file-close" type="button" class="btn icon" title="cerrar" aria-label="cerrar">
184
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
185
+ <path d="M18 6 6 18M6 6l12 12" />
186
+ </svg>
187
+ </button>
188
+ </div>
189
+ </div>
190
+ <pre id="file-content" class="file-preview"></pre>
191
+ </div>
192
+ </dialog>
193
+ </section>
194
+
195
+ <section id="view-providers" class="view">
196
+ <div class="panel">
197
+ <div class="row between">
198
+ <h2>Proveedores</h2>
199
+ <button id="provider-new" class="btn">+ nuevo proveedor</button>
200
+ </div>
201
+ <ul id="provider-list" class="providers"></ul>
202
+ </div>
203
+
204
+ <dialog id="provider-modal" class="modal">
205
+ <form id="provider-form" class="modal-card">
206
+ <div class="row between">
207
+ <h3 id="provider-title">nuevo proveedor</h3>
208
+ <button type="button" id="pf-close" class="btn icon" title="cerrar" aria-label="cerrar">
209
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
210
+ <path d="M18 6 6 18M6 6l12 12" />
211
+ </svg>
212
+ </button>
213
+ </div>
214
+ <div class="row">
215
+ <label class="field"><span>id</span><input id="pf-id" spellcheck="false" placeholder="deepseek" /></label>
216
+ <label class="field"><span>nombre</span><input id="pf-label" spellcheck="false" placeholder="DeepSeek" /></label>
217
+ <label class="field grow"><span>base URL</span><input id="pf-baseurl" spellcheck="false" placeholder="https://api.deepseek.com/v1" /></label>
218
+ </div>
219
+ <div class="row">
220
+ <label class="field grow"><span>API key</span><input id="pf-key" type="password" spellcheck="false" placeholder="dejar vacío para no cambiar" /></label>
221
+ <label class="field grow"><span>modelos (coma, opcional)</span><input id="pf-models" spellcheck="false" placeholder="deepseek-chat, deepseek-reasoner" /></label>
222
+ </div>
223
+ <div class="row">
224
+ <button type="button" id="pf-test" class="btn">probar conexión</button>
225
+ <span class="spacer"></span>
226
+ <button type="button" id="pf-cancel" class="btn">cancelar</button>
227
+ <button type="submit" class="btn primary">guardar</button>
228
+ </div>
229
+ <div id="pf-status" class="summary"></div>
230
+ </form>
231
+ </dialog>
232
+ </section>
233
+
234
+ <section id="view-eval" class="view">
235
+ <div class="panel">
236
+ <h2>Evaluación</h2>
237
+ <label class="field">
238
+ <span>dataset — JSON array o JSONL (una tarea por línea)</span>
239
+ <textarea id="eval-tasks" rows="8" spellcheck="false" placeholder='{"id":"t1","input":"¿2+2?","expect":{"equals":"4"}}'></textarea>
240
+ </label>
241
+ <div class="row">
242
+ <input id="eval-models" placeholder="modelos separados por coma" spellcheck="false" />
243
+ <input id="eval-trials" type="number" min="1" value="1" title="trials" />
244
+ <input id="eval-concurrency" type="number" min="1" value="2" title="concurrencia" />
245
+ <input id="eval-judge" placeholder="judge-model (opcional)" spellcheck="false" />
246
+ <button id="eval-run" class="btn primary">correr</button>
247
+ </div>
248
+ <div id="eval-summary" class="summary"></div>
249
+ <table class="results">
250
+ <thead>
251
+ <tr><th>ok</th><th>tarea</th><th>modelo</th><th>score</th><th>ms</th><th>detalle</th></tr>
252
+ </thead>
253
+ <tbody id="eval-results"></tbody>
254
+ </table>
255
+ </div>
256
+ </section>
257
+
258
+ <section id="view-runs" class="view">
259
+ <div class="panel">
260
+ <div class="row between">
261
+ <h2>Runs</h2>
262
+ <button id="runs-refresh" class="btn">refrescar</button>
263
+ </div>
264
+ <ul id="runs-list" class="runs"></ul>
265
+ <div id="run-detail"></div>
266
+ </div>
267
+ </section>
268
+
269
+ <dialog id="folder-modal" class="modal folder-modal">
270
+ <div class="modal-card">
271
+ <div class="row between">
272
+ <h3>carpeta de trabajo de la sesión</h3>
273
+ <button type="button" id="folder-close" class="btn icon" title="cerrar" aria-label="cerrar">
274
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
275
+ <path d="M18 6 6 18M6 6l12 12" />
276
+ </svg>
277
+ </button>
278
+ </div>
279
+ <div class="folder-toolbar">
280
+ <button type="button" id="folder-up" class="btn icon" title="subir un nivel" aria-label="subir un nivel">
281
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
282
+ <path d="m5 12 7-7 7 7M12 19V5" />
283
+ </svg>
284
+ </button>
285
+ <button type="button" id="folder-home" class="btn icon" title="ir al inicio" aria-label="ir al inicio">
286
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
287
+ <path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8" />
288
+ <path d="M3 10a2 2 0 0 1 .709-1.528l7-6a2 2 0 0 1 2.582 0l7 6A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
289
+ </svg>
290
+ </button>
291
+ <button type="button" id="folder-roots" class="btn icon" title="ir a las unidades" aria-label="ir a las unidades">
292
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
293
+ <path d="M2 12h20" />
294
+ <path d="M5.45 5.11 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.45-6.89A2 2 0 0 0 16.76 4H7.24a2 2 0 0 0-1.79 1.11z" />
295
+ <path d="M6 16h.01M10 16h.01" />
296
+ </svg>
297
+ </button>
298
+ <button type="button" id="folder-new" class="btn icon" title="nueva carpeta acá" aria-label="nueva carpeta acá">
299
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
300
+ <path d="M12 10v6M9 13h6" />
301
+ <path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" />
302
+ </svg>
303
+ </button>
304
+ <nav id="folder-crumbs" class="crumbs" aria-label="ruta actual"></nav>
305
+ </div>
306
+ <div class="folder-search">
307
+ <input id="folder-goto" spellcheck="false" placeholder="filtrar carpetas, o pegá una ruta y Enter" />
308
+ <button type="button" id="folder-go" class="btn">ir</button>
309
+ </div>
310
+ <div id="folder-create" class="folder-create" hidden>
311
+ <input id="folder-new-name" spellcheck="false" placeholder="nombre de la nueva carpeta" />
312
+ <button type="button" id="folder-new-create" class="btn primary">crear</button>
313
+ <button type="button" id="folder-new-cancel" class="btn">cancelar</button>
314
+ </div>
315
+ <ul id="folder-list" class="folders"></ul>
316
+ <div class="folder-footer">
317
+ <span id="folder-status" class="summary"></span>
318
+ <span class="spacer"></span>
319
+ <button type="button" id="folder-cancel" class="btn">cancelar</button>
320
+ <button type="button" id="folder-use" class="btn primary">usar esta carpeta</button>
321
+ </div>
322
+ </div>
323
+ </dialog>
324
+ </main>
325
+
326
+ <dialog id="settings-modal" class="modal settings-modal">
327
+ <div class="modal-card">
328
+ <div class="row between">
329
+ <h3>ajustes del agente</h3>
330
+ <button type="button" id="settings-close" class="btn icon" title="cerrar" aria-label="cerrar">
331
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
332
+ <path d="M18 6 6 18M6 6l12 12" />
333
+ </svg>
334
+ </button>
335
+ </div>
336
+ <label for="mode">Modo</label>
337
+ <select id="mode" title="modo de agente"></select>
338
+ <label for="provider">Proveedor</label>
339
+ <select id="provider" title="proveedor"></select>
340
+ <label for="model">Modelo</label>
341
+ <select id="model" title="modelo"></select>
342
+ <label class="check" title="aprobar automáticamente tools con permiso ask">
343
+ <input id="yes" type="checkbox" /> Aprobar automáticamente las tools (auto)
344
+ </label>
345
+ <div class="row between settings-actions">
346
+ <button type="button" id="settings-providers" class="btn">gestionar proveedores</button>
347
+ <button type="button" id="settings-done" class="btn primary">listo</button>
348
+ </div>
349
+ </div>
350
+ </dialog>
351
+
352
+ <dialog id="palette-modal" class="modal palette-modal">
353
+ <div class="palette">
354
+ <div class="palette-row">
355
+ <svg class="palette-ico" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
356
+ <circle cx="11" cy="11" r="8" />
357
+ <path d="m21 21-4.3-4.3" />
358
+ </svg>
359
+ <input id="palette-input" type="text" placeholder="buscar sesiones y mensajes, o escribí un comando…" spellcheck="false" autocomplete="off" />
360
+ <span class="palette-hint">esc</span>
361
+ </div>
362
+ <ul id="palette-list" class="palette-list"></ul>
363
+ </div>
364
+ </dialog>
365
+
366
+ <script type="module" src="/app.js"></script>
367
+ </body>
368
+ </html>