tycono 0.1.65 → 0.1.67
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/bin/tycono.ts +13 -4
- package/package.json +1 -1
- package/src/api/src/create-server.ts +5 -1
- package/src/api/src/engine/agent-loop.ts +17 -6
- package/src/api/src/engine/context-assembler.ts +156 -48
- package/src/api/src/engine/knowledge-gate.ts +335 -0
- package/src/api/src/engine/llm-adapter.ts +7 -1
- package/src/api/src/engine/runners/claude-cli.ts +98 -116
- package/src/api/src/engine/runners/types.ts +2 -0
- package/src/api/src/engine/tools/executor.ts +3 -5
- package/src/api/src/routes/active-sessions.ts +143 -0
- package/src/api/src/routes/coins.ts +137 -0
- package/src/api/src/routes/execute.ts +158 -48
- package/src/api/src/routes/knowledge.ts +30 -0
- package/src/api/src/routes/operations.ts +48 -11
- package/src/api/src/routes/sessions.ts +1 -1
- package/src/api/src/routes/setup.ts +68 -1
- package/src/api/src/routes/speech.ts +334 -143
- package/src/api/src/services/activity-stream.ts +1 -1
- package/src/api/src/services/job-manager.ts +185 -9
- package/src/api/src/services/port-registry.ts +222 -0
- package/src/api/src/services/scaffold.ts +90 -0
- package/src/api/src/services/session-store.ts +75 -5
- package/src/web/dist/assets/index-BMR4T6Uy.js +109 -0
- package/src/web/dist/assets/index-C5M-8dqq.css +1 -0
- package/src/web/dist/assets/{preview-app-qIFqrb-y.js → preview-app-BJAaiJcV.js} +1 -1
- package/src/web/dist/index.html +2 -2
- package/templates/skills/_manifest.json +6 -0
- package/templates/skills/agent-browser/SKILL.md +159 -0
- package/templates/skills/agent-browser/meta.json +19 -0
- package/templates/teams/agency.json +3 -3
- package/templates/teams/research.json +3 -3
- package/templates/teams/startup.json +3 -3
- package/src/web/dist/assets/index-B3dNhn76.js +0 -101
- package/src/web/dist/assets/index-C7IEX_o_.css +0 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { Router, Request, Response, NextFunction } from 'express';
|
|
2
|
-
import { readFile, listFiles, fileExists } from '../services/file-reader.js';
|
|
2
|
+
import { readFile, listFiles, fileExists, COMPANY_ROOT } from '../services/file-reader.js';
|
|
3
3
|
import { extractBoldKeyValues } from '../services/markdown-parser.js';
|
|
4
4
|
import path from 'node:path';
|
|
5
|
+
import fs from 'node:fs';
|
|
5
6
|
|
|
6
7
|
export const operationsRouter = Router();
|
|
7
8
|
|
|
@@ -39,16 +40,26 @@ operationsRouter.get('/standups/:date', (req: Request, res: Response, next: Next
|
|
|
39
40
|
}
|
|
40
41
|
});
|
|
41
42
|
|
|
42
|
-
// --- Waves ---
|
|
43
|
+
// --- Waves (JSON-only) ---
|
|
43
44
|
operationsRouter.get('/waves', (_req: Request, res: Response, next: NextFunction) => {
|
|
44
45
|
try {
|
|
45
|
-
const files = listFiles('operations/waves');
|
|
46
|
+
const files = listFiles('operations/waves', '*.json');
|
|
46
47
|
const waves = files
|
|
47
|
-
.filter(f => f.endsWith('.md'))
|
|
48
48
|
.map(f => {
|
|
49
|
-
const id = path.basename(f, '.
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
const id = path.basename(f, '.json');
|
|
50
|
+
try {
|
|
51
|
+
const data = JSON.parse(readFile(`operations/waves/${f}`));
|
|
52
|
+
return {
|
|
53
|
+
id,
|
|
54
|
+
timestamp: id,
|
|
55
|
+
directive: data.directive ?? '',
|
|
56
|
+
rolesCount: data.roles?.length ?? 0,
|
|
57
|
+
startedAt: data.startedAt ?? '',
|
|
58
|
+
...(data.commit ? { commit: data.commit } : {}),
|
|
59
|
+
};
|
|
60
|
+
} catch {
|
|
61
|
+
return { id, timestamp: id, directive: '', rolesCount: 0, startedAt: '' };
|
|
62
|
+
}
|
|
52
63
|
})
|
|
53
64
|
.sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
54
65
|
|
|
@@ -61,13 +72,39 @@ operationsRouter.get('/waves', (_req: Request, res: Response, next: NextFunction
|
|
|
61
72
|
operationsRouter.get('/waves/:id', (req: Request, res: Response, next: NextFunction) => {
|
|
62
73
|
try {
|
|
63
74
|
const { id } = req.params;
|
|
64
|
-
const
|
|
65
|
-
|
|
75
|
+
const jsonPath = `operations/waves/${id}.json`;
|
|
76
|
+
|
|
77
|
+
if (!fileExists(jsonPath)) {
|
|
66
78
|
res.status(404).json({ error: `Wave not found: ${id}` });
|
|
67
79
|
return;
|
|
68
80
|
}
|
|
69
|
-
|
|
70
|
-
|
|
81
|
+
|
|
82
|
+
const data = JSON.parse(readFile(jsonPath));
|
|
83
|
+
res.json({ id, timestamp: id, replay: data });
|
|
84
|
+
} catch (err) {
|
|
85
|
+
next(err);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// PATCH /waves/:id — update wave metadata (e.g. commit info)
|
|
90
|
+
operationsRouter.patch('/waves/:id', (req: Request, res: Response, next: NextFunction) => {
|
|
91
|
+
try {
|
|
92
|
+
const { id } = req.params;
|
|
93
|
+
const jsonPath = `operations/waves/${id}.json`;
|
|
94
|
+
|
|
95
|
+
if (!fileExists(jsonPath)) {
|
|
96
|
+
res.status(404).json({ error: `Wave not found: ${id}` });
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const data = JSON.parse(readFile(jsonPath));
|
|
101
|
+
const { commitSha, commitMessage, committedAt } = req.body ?? {};
|
|
102
|
+
if (commitSha) {
|
|
103
|
+
data.commit = { sha: commitSha, message: commitMessage ?? '', committedAt: committedAt ?? new Date().toISOString() };
|
|
104
|
+
}
|
|
105
|
+
const absPath = path.resolve(COMPANY_ROOT, jsonPath);
|
|
106
|
+
fs.writeFileSync(absPath, JSON.stringify(data, null, 2), 'utf-8');
|
|
107
|
+
res.json({ ok: true });
|
|
71
108
|
} catch (err) {
|
|
72
109
|
next(err);
|
|
73
110
|
}
|
|
@@ -18,7 +18,7 @@ sessionsRouter.post('/', (req, res) => {
|
|
|
18
18
|
res.status(400).json({ error: 'roleId is required' });
|
|
19
19
|
return;
|
|
20
20
|
}
|
|
21
|
-
const session = createSession(roleId, mode ?? 'talk');
|
|
21
|
+
const session = createSession(roleId, { mode: mode ?? 'talk' });
|
|
22
22
|
res.status(201).json(session);
|
|
23
23
|
});
|
|
24
24
|
|
|
@@ -9,7 +9,7 @@ import fs from 'node:fs';
|
|
|
9
9
|
import path from 'node:path';
|
|
10
10
|
import { execSync } from 'node:child_process';
|
|
11
11
|
import os from 'node:os';
|
|
12
|
-
import { scaffold, getAvailableTeams, loadTeam } from '../services/scaffold.js';
|
|
12
|
+
import { scaffold, getAvailableTeams, loadTeam, getRequiredTools, installSkillTools } from '../services/scaffold.js';
|
|
13
13
|
import type { ScaffoldConfig } from '../services/scaffold.js';
|
|
14
14
|
import { importKnowledge } from '../services/knowledge-importer.js';
|
|
15
15
|
import { gitInit } from '../services/git-save.js';
|
|
@@ -342,3 +342,70 @@ setupRouter.get('/teams', (_req, res) => {
|
|
|
342
342
|
}));
|
|
343
343
|
res.json(result);
|
|
344
344
|
});
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* POST /api/setup/required-tools
|
|
348
|
+
* Check which tools are needed for a team's skills.
|
|
349
|
+
*/
|
|
350
|
+
setupRouter.post('/required-tools', (req, res) => {
|
|
351
|
+
const { team } = req.body;
|
|
352
|
+
if (!team || typeof team !== 'string') {
|
|
353
|
+
res.json({ tools: [] });
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const roles = loadTeam(team);
|
|
358
|
+
const skillIds = new Set<string>();
|
|
359
|
+
for (const role of roles) {
|
|
360
|
+
if (role.defaultSkills) {
|
|
361
|
+
for (const s of role.defaultSkills) skillIds.add(s);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const tools = getRequiredTools(Array.from(skillIds));
|
|
366
|
+
res.json({ tools });
|
|
367
|
+
});
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* POST /api/setup/install-tools (SSE)
|
|
371
|
+
* Install CLI tools required by team skills with progress streaming.
|
|
372
|
+
*/
|
|
373
|
+
setupRouter.post('/install-tools', (req, res) => {
|
|
374
|
+
const { team } = req.body;
|
|
375
|
+
if (!team || typeof team !== 'string') {
|
|
376
|
+
res.status(400).json({ error: 'team is required' });
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const roles = loadTeam(team);
|
|
381
|
+
const skillIds = new Set<string>();
|
|
382
|
+
for (const role of roles) {
|
|
383
|
+
if (role.defaultSkills) {
|
|
384
|
+
for (const s of role.defaultSkills) skillIds.add(s);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// SSE headers
|
|
389
|
+
res.writeHead(200, {
|
|
390
|
+
'Content-Type': 'text/event-stream',
|
|
391
|
+
'Cache-Control': 'no-cache',
|
|
392
|
+
'Connection': 'keep-alive',
|
|
393
|
+
'X-Accel-Buffering': 'no',
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
const sendSSE = (event: string, data: unknown) => {
|
|
397
|
+
res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
installSkillTools(Array.from(skillIds), {
|
|
401
|
+
onChecking: (tool) => sendSSE('checking', { tool }),
|
|
402
|
+
onInstalling: (tool) => sendSSE('installing', { tool }),
|
|
403
|
+
onInstalled: (tool) => sendSSE('installed', { tool }),
|
|
404
|
+
onSkipped: (tool, reason) => sendSSE('skipped', { tool, reason }),
|
|
405
|
+
onError: (tool, error) => sendSSE('error', { tool, error }),
|
|
406
|
+
onDone: (stats) => {
|
|
407
|
+
sendSSE('done', stats);
|
|
408
|
+
res.end();
|
|
409
|
+
},
|
|
410
|
+
});
|
|
411
|
+
});
|