@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.
- package/CHANGELOG.md +18 -0
- package/README.md +13 -25
- package/SECURITY.md +3 -4
- package/harness/packages/cli/src/cli.js +0 -3
- package/harness/packages/cli/src/commands/bridge.js +0 -1
- package/harness/packages/cli/src/commands/repl.js +3 -3
- package/harness/packages/cli/src/commands/run.js +1 -1
- package/harness/packages/cli/src/commands/server.js +1 -1
- package/harness/packages/cli/src/commands/tui.js +1 -1
- package/harness/packages/cli/src/lib/util.js +2 -2
- package/harness/packages/cli/src/tui/app.js +2 -2
- package/harness/packages/cli/test/tunnel.test.js +5 -32
- package/harness/packages/core/src/agents/index.js +13 -41
- package/harness/packages/core/src/config/app.js +0 -4
- package/harness/packages/core/src/config/home.js +1 -20
- package/harness/packages/core/src/config/index.js +5 -8
- package/harness/packages/core/src/extensions/load.js +22 -0
- package/harness/packages/core/src/frontmatter.js +32 -0
- package/harness/packages/core/src/hooks/index.js +2 -16
- package/harness/packages/core/src/index.js +2 -14
- package/harness/packages/core/src/plugins/index.js +2 -16
- package/harness/packages/core/src/procs/project.js +68 -0
- package/harness/packages/core/src/procs/static.js +17 -0
- package/harness/packages/core/src/rules/index.js +8 -27
- package/harness/packages/core/src/skills/index.js +8 -19
- package/harness/packages/core/src/storage/sqlite.js +595 -690
- package/harness/packages/core/src/tunnel.js +9 -147
- package/harness/packages/core/test/home.test.js +2 -35
- package/harness/packages/core/test/procs.test.js +3 -64
- package/harness/packages/core/test/storage.test.js +1 -12
- package/harness/packages/server/public/app.js +2 -19
- package/harness/packages/server/public/appearance.js +2 -56
- package/harness/packages/server/public/boot.js +2 -2
- package/harness/packages/server/public/cards.js +2 -21
- package/harness/packages/server/public/chat.js +0 -16
- package/harness/packages/server/public/chatFormat.js +0 -11
- package/harness/packages/server/public/chrome.js +2 -5
- package/harness/packages/server/public/commands.js +1 -2
- package/harness/packages/server/public/explorer.js +7 -10
- package/harness/packages/server/public/icons/icon-128x128.png +0 -0
- package/harness/packages/server/public/icons/icon-144x144.png +0 -0
- package/harness/packages/server/public/icons/icon-152x152.png +0 -0
- package/harness/packages/server/public/icons/icon-192x192.png +0 -0
- package/harness/packages/server/public/icons/icon-384x384.png +0 -0
- package/harness/packages/server/public/icons/icon-512x512.png +0 -0
- package/harness/packages/server/public/icons/icon-72x72.png +0 -0
- package/harness/packages/server/public/icons/icon-96x96.png +0 -0
- package/harness/packages/server/public/icons/logo.png +0 -0
- package/harness/packages/server/public/icons/logo_light.png +0 -0
- package/harness/packages/server/public/index.html +1228 -1326
- package/harness/packages/server/public/landing/boot.js +2 -3
- package/harness/packages/server/public/landing/index.html +3 -367
- package/harness/packages/server/public/logo.png +0 -0
- package/harness/packages/server/public/settings.js +1255 -1322
- package/harness/packages/server/public/settingsNav.js +0 -1
- package/harness/packages/server/public/styles.css +2341 -2867
- package/harness/packages/server/public/system.js +356 -495
- package/harness/packages/server/public/voice.js +6 -22
- package/harness/packages/server/src/auth.js +4 -15
- package/harness/packages/server/src/cli.js +1 -1
- package/harness/packages/server/src/lib/agents.js +13 -27
- package/harness/packages/server/src/lib/appearance.js +3 -22
- package/harness/packages/server/src/lib/channels/telegram/commands.js +1 -1
- package/harness/packages/server/src/lib/definitions.js +40 -0
- package/harness/packages/server/src/lib/skills.js +14 -21
- package/harness/packages/server/src/lib/ttsSettings.js +2 -2
- package/harness/packages/server/src/lib/workspace.js +9 -11
- package/harness/packages/server/src/routes/chat.js +0 -43
- package/harness/packages/server/src/routes/preview.js +5 -22
- package/harness/packages/server/src/routes/procs.js +2 -4
- package/harness/packages/server/src/routes/tts.js +1 -1
- package/harness/packages/server/src/server.js +1 -5
- package/harness/packages/server/test/appearance-route.test.js +3 -3
- package/harness/packages/server/test/appearance.test.js +12 -38
- package/harness/packages/server/test/chatFormat.test.js +0 -8
- package/harness/packages/server/test/consoleTabs.test.js +4 -4
- package/harness/packages/server/test/ops.test.js +8 -56
- package/harness/packages/server/test/preview.test.js +2 -42
- package/harness/packages/server/test/security.test.js +194 -370
- package/harness/packages/server/test/settingsNav.test.js +2 -2
- package/harness/packages/server/test/tts.test.js +4 -4
- package/harness/tamnora.example.json +1 -1
- package/package.json +2 -2
- package/harness/packages/cli/src/commands/eval.js +0 -186
- package/harness/packages/core/src/eval/dataset.js +0 -47
- package/harness/packages/core/src/eval/judge.js +0 -39
- package/harness/packages/core/src/eval/report.js +0 -48
- package/harness/packages/core/src/eval/runTask.js +0 -62
- package/harness/packages/core/src/eval/runner.js +0 -153
- package/harness/packages/core/src/eval/scorers.js +0 -217
- package/harness/packages/core/src/eval/task.js +0 -59
- package/harness/packages/core/src/procs/detect.js +0 -149
- package/harness/packages/core/test/eval.test.js +0 -144
- package/harness/packages/server/public/icons (1).zip +0 -0
- package/harness/packages/server/src/lib/advisor.js +0 -198
- package/harness/packages/server/src/routes/advisor.js +0 -79
- package/harness/packages/server/src/routes/eval.js +0 -100
- package/harness/packages/server/test/advisor.test.js +0 -249
- 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
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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 -> []. */
|