@danieltmn/tamnora 0.25.1 → 0.26.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 (99) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/README.md +13 -25
  3. package/SECURITY.md +3 -4
  4. package/harness/packages/cli/src/cli.js +0 -3
  5. package/harness/packages/cli/src/commands/bridge.js +0 -1
  6. package/harness/packages/cli/src/commands/repl.js +3 -3
  7. package/harness/packages/cli/src/commands/run.js +1 -1
  8. package/harness/packages/cli/src/commands/server.js +1 -1
  9. package/harness/packages/cli/src/commands/tui.js +1 -1
  10. package/harness/packages/cli/src/lib/util.js +2 -2
  11. package/harness/packages/cli/src/tui/app.js +2 -2
  12. package/harness/packages/cli/test/tunnel.test.js +5 -32
  13. package/harness/packages/core/src/agents/index.js +13 -41
  14. package/harness/packages/core/src/config/app.js +0 -4
  15. package/harness/packages/core/src/config/home.js +1 -20
  16. package/harness/packages/core/src/config/index.js +5 -8
  17. package/harness/packages/core/src/extensions/load.js +22 -0
  18. package/harness/packages/core/src/frontmatter.js +32 -0
  19. package/harness/packages/core/src/hooks/index.js +2 -16
  20. package/harness/packages/core/src/index.js +2 -14
  21. package/harness/packages/core/src/plugins/index.js +2 -16
  22. package/harness/packages/core/src/procs/project.js +68 -0
  23. package/harness/packages/core/src/procs/static.js +17 -0
  24. package/harness/packages/core/src/rules/index.js +8 -27
  25. package/harness/packages/core/src/skills/index.js +8 -19
  26. package/harness/packages/core/src/storage/sqlite.js +595 -690
  27. package/harness/packages/core/src/tunnel.js +9 -147
  28. package/harness/packages/core/test/home.test.js +2 -35
  29. package/harness/packages/core/test/procs.test.js +3 -64
  30. package/harness/packages/core/test/storage.test.js +1 -12
  31. package/harness/packages/server/public/app.js +2 -19
  32. package/harness/packages/server/public/appearance.js +2 -56
  33. package/harness/packages/server/public/boot.js +2 -2
  34. package/harness/packages/server/public/cards.js +2 -21
  35. package/harness/packages/server/public/chat.js +0 -16
  36. package/harness/packages/server/public/chatFormat.js +0 -11
  37. package/harness/packages/server/public/chrome.js +2 -5
  38. package/harness/packages/server/public/commands.js +1 -2
  39. package/harness/packages/server/public/explorer.js +7 -10
  40. package/harness/packages/server/public/icons/icon-128x128.png +0 -0
  41. package/harness/packages/server/public/icons/icon-144x144.png +0 -0
  42. package/harness/packages/server/public/icons/icon-152x152.png +0 -0
  43. package/harness/packages/server/public/icons/icon-192x192.png +0 -0
  44. package/harness/packages/server/public/icons/icon-384x384.png +0 -0
  45. package/harness/packages/server/public/icons/icon-512x512.png +0 -0
  46. package/harness/packages/server/public/icons/icon-72x72.png +0 -0
  47. package/harness/packages/server/public/icons/icon-96x96.png +0 -0
  48. package/harness/packages/server/public/icons/logo.png +0 -0
  49. package/harness/packages/server/public/icons/logo_light.png +0 -0
  50. package/harness/packages/server/public/index.html +1228 -1326
  51. package/harness/packages/server/public/landing/boot.js +2 -3
  52. package/harness/packages/server/public/landing/index.html +3 -367
  53. package/harness/packages/server/public/logo.png +0 -0
  54. package/harness/packages/server/public/settings.js +1255 -1322
  55. package/harness/packages/server/public/settingsNav.js +0 -1
  56. package/harness/packages/server/public/styles.css +2341 -2867
  57. package/harness/packages/server/public/system.js +356 -495
  58. package/harness/packages/server/public/voice.js +6 -22
  59. package/harness/packages/server/src/auth.js +4 -15
  60. package/harness/packages/server/src/cli.js +1 -1
  61. package/harness/packages/server/src/lib/agents.js +13 -27
  62. package/harness/packages/server/src/lib/appearance.js +3 -22
  63. package/harness/packages/server/src/lib/channels/telegram/commands.js +1 -1
  64. package/harness/packages/server/src/lib/definitions.js +40 -0
  65. package/harness/packages/server/src/lib/skills.js +14 -21
  66. package/harness/packages/server/src/lib/ttsSettings.js +2 -2
  67. package/harness/packages/server/src/lib/workspace.js +9 -11
  68. package/harness/packages/server/src/routes/chat.js +0 -43
  69. package/harness/packages/server/src/routes/preview.js +5 -22
  70. package/harness/packages/server/src/routes/procs.js +2 -4
  71. package/harness/packages/server/src/routes/tts.js +1 -1
  72. package/harness/packages/server/src/server.js +1 -5
  73. package/harness/packages/server/test/appearance-route.test.js +3 -3
  74. package/harness/packages/server/test/appearance.test.js +12 -38
  75. package/harness/packages/server/test/chatFormat.test.js +0 -8
  76. package/harness/packages/server/test/consoleTabs.test.js +4 -4
  77. package/harness/packages/server/test/ops.test.js +8 -56
  78. package/harness/packages/server/test/preview.test.js +2 -42
  79. package/harness/packages/server/test/security.test.js +194 -370
  80. package/harness/packages/server/test/settingsNav.test.js +2 -2
  81. package/harness/packages/server/test/tts.test.js +4 -4
  82. package/harness/tamnora.example.json +1 -1
  83. package/package.json +2 -2
  84. package/harness/packages/cli/src/commands/eval.js +0 -186
  85. package/harness/packages/core/src/eval/dataset.js +0 -47
  86. package/harness/packages/core/src/eval/judge.js +0 -39
  87. package/harness/packages/core/src/eval/report.js +0 -48
  88. package/harness/packages/core/src/eval/runTask.js +0 -62
  89. package/harness/packages/core/src/eval/runner.js +0 -153
  90. package/harness/packages/core/src/eval/scorers.js +0 -217
  91. package/harness/packages/core/src/eval/task.js +0 -59
  92. package/harness/packages/core/src/procs/detect.js +0 -149
  93. package/harness/packages/core/test/eval.test.js +0 -144
  94. package/harness/packages/server/public/icons (1).zip +0 -0
  95. package/harness/packages/server/src/lib/advisor.js +0 -198
  96. package/harness/packages/server/src/routes/advisor.js +0 -79
  97. package/harness/packages/server/src/routes/eval.js +0 -100
  98. package/harness/packages/server/test/advisor.test.js +0 -249
  99. package/harness/scripts/example-dataset.jsonl +0 -4
@@ -0,0 +1,68 @@
1
+ // Procesos de desarrollo declarados por el proyecto en `.tamnora/procs.json`.
2
+ // No se autodetecta nada: el usuario declara como arrancar cada servidor.
3
+
4
+ import { existsSync, readFileSync } from 'node:fs';
5
+ import path from 'node:path';
6
+
7
+ export const DEFAULT_PROCESS_ALLOW = [
8
+ 'npm',
9
+ 'node',
10
+ 'npx',
11
+ 'pnpm',
12
+ 'yarn',
13
+ 'bun',
14
+ 'bunx',
15
+ 'php',
16
+ 'python',
17
+ 'python3',
18
+ 'composer',
19
+ ];
20
+
21
+ /** Archivo por proyecto (relativo a su raiz) que define sus procesos de dev. */
22
+ export const PROCS_FILE = '.tamnora/procs.json';
23
+
24
+ /** True si `target` es `root` o vive dentro de el (sin salirse por `..`). */
25
+ function isInside(root, target) {
26
+ const rel = path.relative(root, target);
27
+ return rel === '' || (!rel.startsWith('..') && !path.isAbsolute(rel));
28
+ }
29
+
30
+ /**
31
+ * Procesos definidos a mano por el proyecto en `<root>/.tamnora/procs.json`.
32
+ * Formato: `{ "processes": [{ label?, dir?, command, args?, port? }] }` o un array
33
+ * directo. `dir` es relativo a la raiz y debe quedar dentro de ella. Cada chip
34
+ * sigue pasando por la whitelist (`processes.allow`) al arrancar.
35
+ */
36
+ export function loadProjectProcs(root) {
37
+ const file = path.join(root, PROCS_FILE);
38
+ if (!existsSync(file)) return [];
39
+ const raw = readJson(file);
40
+ const list = Array.isArray(raw) ? raw : Array.isArray(raw?.processes) ? raw.processes : [];
41
+ const chips = [];
42
+ for (const entry of list) {
43
+ if (!entry || typeof entry !== 'object') continue;
44
+ const command = String(entry.command ?? '').trim();
45
+ if (!command) continue;
46
+ const rel = String(entry.dir ?? '').trim().replace(/^[/\\]+/, '');
47
+ const cwd = path.resolve(root, rel || '.');
48
+ if (!isInside(root, cwd) || !existsSync(cwd)) continue;
49
+ const port = entry.port ? Number(entry.port) : undefined;
50
+ chips.push({
51
+ label: String(entry.label ?? command).trim() || command,
52
+ command,
53
+ args: Array.isArray(entry.args) ? entry.args.map(String) : [],
54
+ cwd,
55
+ port: Number.isInteger(port) && port > 0 ? port : undefined,
56
+ source: 'project',
57
+ });
58
+ }
59
+ return chips;
60
+ }
61
+
62
+ function readJson(file) {
63
+ try {
64
+ return JSON.parse(readFileSync(file, 'utf8'));
65
+ } catch {
66
+ return null;
67
+ }
68
+ }
@@ -0,0 +1,17 @@
1
+ // Chip para servir un directorio como sitio estatico con el servidor sin
2
+ // dependencias. Lo usa la vista previa de un HTML en el explorador.
3
+
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ const STATIC_SERVER = fileURLToPath(new URL('../../../../scripts/static-server.mjs', import.meta.url));
7
+ const STATIC_PORT = 8080;
8
+
9
+ export function staticServerChip(dir, { port = STATIC_PORT, label } = {}) {
10
+ return {
11
+ label: label ?? `sitio estático (${port})`,
12
+ command: process.execPath,
13
+ args: [STATIC_SERVER, dir, String(port)],
14
+ cwd: dir,
15
+ port,
16
+ };
17
+ }
@@ -5,36 +5,17 @@
5
5
  import { readFile } from 'node:fs/promises';
6
6
  import path from 'node:path';
7
7
  import { globToRegExp, globFiles } from '../tools/glob.js';
8
+ import { parseFrontmatter, parseListValue } from '../frontmatter.js';
8
9
 
9
10
  /** Parsea un archivo de reglas: frontmatter (name, paths/globs) + body. */
10
11
  export function parseRuleMarkdown(text, fallbackId = '') {
11
- const source = String(text ?? '');
12
- let name = fallbackId;
13
- let paths = [];
14
- let body = source.trim();
15
- const match = source.match(/^---\s*\r?\n([\s\S]*?)\r?\n---\s*\r?\n?([\s\S]*)$/);
16
- if (match) {
17
- body = match[2].trim();
18
- for (const line of match[1].split(/\r?\n/)) {
19
- const kv = line.match(/^([A-Za-z][\w-]*)\s*:\s*(.*)$/);
20
- if (!kv) continue;
21
- const key = kv[1].toLowerCase();
22
- const value = kv[2].trim();
23
- if (key === 'name') name = value.replace(/^["']|["']$/g, '');
24
- else if (key === 'paths' || key === 'globs' || key === 'path') paths = parseList(value);
25
- }
26
- }
27
- return { name: name || fallbackId, paths: normalizePaths(paths), body };
28
- }
29
-
30
- function parseList(value) {
31
- const raw = String(value ?? '').trim();
32
- if (!raw) return [];
33
- const inner = raw.startsWith('[') && raw.endsWith(']') ? raw.slice(1, -1) : raw;
34
- return inner
35
- .split(',')
36
- .map((s) => s.trim().replace(/^["']|["']$/g, ''))
37
- .filter(Boolean);
12
+ const { fields, body } = parseFrontmatter(text);
13
+ const listed = fields.paths ?? fields.globs ?? fields.path;
14
+ return {
15
+ name: fields.name || fallbackId,
16
+ paths: normalizePaths(listed === undefined ? [] : parseListValue(listed)),
17
+ body,
18
+ };
38
19
  }
39
20
 
40
21
  function normalizePaths(paths) {
@@ -5,28 +5,17 @@
5
5
  import { readdirSync, readFileSync, statSync } from 'node:fs';
6
6
  import { mkdir, writeFile } from 'node:fs/promises';
7
7
  import path from 'node:path';
8
+ import { parseFrontmatter } from '../frontmatter.js';
8
9
 
9
10
  /** Parse a SKILL.md: frontmatter `--- key: value ---` plus body. */
10
11
  export function parseSkillMarkdown(text, fallbackId = '') {
11
- const source = String(text ?? '');
12
- let name = fallbackId;
13
- let description = '';
14
- let when = '';
15
- let body = source.trim();
16
- const match = source.match(/^---\s*\r?\n([\s\S]*?)\r?\n---\s*\r?\n?([\s\S]*)$/);
17
- if (match) {
18
- body = match[2].trim();
19
- for (const line of match[1].split(/\r?\n/)) {
20
- const kv = line.match(/^([A-Za-z][\w-]*)\s*:\s*(.*)$/);
21
- if (!kv) continue;
22
- const key = kv[1].toLowerCase();
23
- const value = kv[2].trim().replace(/^["']|["']$/g, '');
24
- if (key === 'name') name = value;
25
- else if (key === 'description') description = value;
26
- else if (key === 'when' || key === 'when_to_use') when = value;
27
- }
28
- }
29
- return { name: name || fallbackId, description, when, body };
12
+ const { fields, body } = parseFrontmatter(text);
13
+ return {
14
+ name: fields.name || fallbackId,
15
+ description: fields.description || '',
16
+ when: fields.when || fields.when_to_use || '',
17
+ body,
18
+ };
30
19
  }
31
20
 
32
21
  /** List the skills under a root (`<root>/<slug>/SKILL.md`). Missing root -> []. */