agentlas 0.4.0 → 0.5.2
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/README.md +67 -20
- package/engine/agentlas-banner.cjs +49 -18
- package/engine/agentlas-doctor.cjs +25 -2
- package/engine/agentlas-i18n.cjs +12 -0
- package/engine/agentlas-input.cjs +7 -0
- package/engine/agentlas-parity.cjs +58 -8
- package/engine/agentlas-repl.cjs +50 -2
- package/engine/agentlas-ui.cjs +1 -1
- package/engine/agentlas.cjs +346 -55
- package/engine/architecture.data.json +5 -1
- package/package.json +1 -1
- package/test/smoke.sh +14 -0
package/README.md
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
# agentlas
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
```
|
|
4
|
+
█████╗ ██████╗ ███████╗███╗ ██╗████████╗██╗ █████╗ ███████╗
|
|
5
|
+
██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝██║ ██╔══██╗██╔════╝
|
|
6
|
+
███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ██║ ███████║███████╗
|
|
7
|
+
██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ██║ ██╔══██║╚════██║
|
|
8
|
+
██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ███████╗██║ ██║███████║
|
|
9
|
+
╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
**The operating system for agents — in your terminal.** Chat with your AI
|
|
13
|
+
agents and teams, build new ones, and run the full Agentlas OS surface
|
|
14
|
+
(`build` · `search` · `install` · `storm` · `network` · …) from one command.
|
|
15
|
+
Claude Code style, standalone: **no desktop app required.**
|
|
5
16
|
|
|
6
17
|
```sh
|
|
7
18
|
npm install -g agentlas
|
|
@@ -40,31 +51,67 @@ Windows(미검증): `powershell -ExecutionPolicy Bypass -File install.ps1`
|
|
|
40
51
|
## 사용
|
|
41
52
|
|
|
42
53
|
```sh
|
|
43
|
-
agentlas # 대화형 TUI (
|
|
44
|
-
agentlas
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
54
|
+
agentlas # 대화형 TUI (워드마크 → 할 일 입력 → 스트리밍 REPL)
|
|
55
|
+
agentlas "할 일" # 자동 라우팅 후 1회 실행
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**대화 & 실행**
|
|
59
|
+
```sh
|
|
60
|
+
agentlas <agent> # 해당 에이전트와 대화 (예: agentlas seo)
|
|
61
|
+
agentlas run [agent] "프롬프트" # 1회 실행 (agent 생략 시 자동 라우팅, prompt 없으면 stdin)
|
|
62
|
+
agentlas firm <firm> "프롬프트" # 회사(팀) CEO에 위임
|
|
63
|
+
agentlas chats [n] # 최근 대화 목록
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**에이전트 & 허브** (Agentlas OS 표면)
|
|
67
|
+
```sh
|
|
68
|
+
agentlas search "할 일" # Hub에서 에이전트 발견 (hep-search)
|
|
69
|
+
agentlas install <slug> # Hub 에이전트 설치 (hep-cloud)
|
|
70
|
+
agentlas build "요청" # 에이전트/팀 빌드·수리·패키징 (hep-build)
|
|
71
|
+
agentlas upload <경로> # 에이전트 패키징+Hub 배포 (hep-upload)
|
|
72
|
+
agentlas connect # Telegram/플랫폼 연결 (hep-connect)
|
|
49
73
|
agentlas import <폴더> # 로컬 에이전트/팀 임포트
|
|
50
|
-
agentlas
|
|
51
|
-
|
|
74
|
+
agentlas list # 설치된 에이전트/회사 + 활성 런타임
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
**실행 엔진**
|
|
78
|
+
```sh
|
|
79
|
+
agentlas storm "목표" # 견고 파이프라인 라우팅→검증→실행 (Stormbreaker) [--research]
|
|
80
|
+
agentlas swarm "목표" # emergent 에이전트 스웜 [--parallel N]
|
|
81
|
+
agentlas network "요청" # A2A 태스크포스로 분해 (hep-network)
|
|
82
|
+
agentlas call "a,b" "컨텍스트" # 지정 에이전트 호출 (hep-call)
|
|
83
|
+
agentlas browser # 실제 브라우저 하드포인트 (hep-browser)
|
|
84
|
+
agentlas route "요청" # 라우팅 미리보기 (실행 없음)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**지식 & 리서치**
|
|
88
|
+
```sh
|
|
89
|
+
agentlas research <sub> # Research Engine (status|gather|search|read|plan)
|
|
90
|
+
agentlas ontology <sub> # 프로젝트 지식 (status|list|add)
|
|
91
|
+
agentlas journal <sub> # Stormbreaker 저널 (status|verify|repair|gate)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**계정 & 운영**
|
|
95
|
+
```sh
|
|
52
96
|
agentlas login | logout | whoami # Agentlas Cloud 로그인 (브라우저 플로우)
|
|
53
|
-
agentlas automation list|add|on|off|remove|runs
|
|
54
|
-
agentlas
|
|
55
|
-
agentlas automation daemon # 상주 실행기 — 앱 없이 예약 자동화 실행 (앱과 리스 공유)
|
|
56
|
-
agentlas cloud search "찾는 일" # 마켓플레이스 검색 (로그인 불필요)
|
|
57
|
-
agentlas cloud install <slug> # 마켓플레이스에서 에이전트 설치
|
|
58
|
-
agentlas usage # 로컬 사용 현황 (실행/메시지/자동화)
|
|
59
|
-
agentlas telegram # 텔레그램 바인딩 현황 (읽기 전용)
|
|
60
|
-
agentlas creds / env # 자격증명 · env
|
|
97
|
+
agentlas automation <sub> # list|add|on|off|remove|run <id>|runs|daemon (로컬 스케줄러)
|
|
98
|
+
agentlas creds <sub> · env # 자격증명 볼트 · env
|
|
61
99
|
agentlas multimodal # 이미지/영상/음성 provider
|
|
100
|
+
agentlas usage · telegram · mcp # 사용 현황 · 텔레그램 · MCP 서버
|
|
62
101
|
agentlas doctor # 런타임/데이터 점검
|
|
63
|
-
agentlas
|
|
64
|
-
agentlas
|
|
102
|
+
agentlas update # npm 최신판 확인
|
|
103
|
+
agentlas setup # 온보딩 다시 실행
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**고급**
|
|
107
|
+
```sh
|
|
108
|
+
agentlas hep <sub…> # 전체 Hephaestus 패스스루 (wizard·security·cards·ao·plugins…)
|
|
109
|
+
agentlas netadmin <sub> # 로컬 네트워크 관리 (init|status|reindex|bench)
|
|
110
|
+
agentlas cloud <sub> # 에이전트 패키징 (wizard|security|bundle|package|publish)
|
|
65
111
|
```
|
|
66
112
|
|
|
67
113
|
공통 옵션: `--runtime claude-code|codex|gemini` · `--permission read|write|full`
|
|
114
|
+
REPL 안에서는 `/`로 명령 팔레트 (`/build` `/search` `/storm` `/network` …).
|
|
68
115
|
|
|
69
116
|
## 동작 방식
|
|
70
117
|
|
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/*
|
|
3
|
-
* Agentlas terminal splash —
|
|
3
|
+
* Agentlas terminal splash — AGENTLAS wordmark banner + status card.
|
|
4
4
|
*/
|
|
5
5
|
const path = require("node:path");
|
|
6
6
|
const os = require("node:os");
|
|
7
7
|
|
|
8
|
-
//
|
|
9
|
-
const
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
8
|
+
// AGENTLAS wordmark (block letters). Rendered with a brand gradient across columns.
|
|
9
|
+
const WORDMARK = [
|
|
10
|
+
" █████╗ ██████╗ ███████╗███╗ ██╗████████╗██╗ █████╗ ███████╗",
|
|
11
|
+
" ██╔══██╗██╔════╝ ██╔════╝████╗ ██║╚══██╔══╝██║ ██╔══██╗██╔════╝",
|
|
12
|
+
" ███████║██║ ███╗█████╗ ██╔██╗ ██║ ██║ ██║ ███████║███████╗",
|
|
13
|
+
" ██╔══██║██║ ██║██╔══╝ ██║╚██╗██║ ██║ ██║ ██╔══██║╚════██║",
|
|
14
|
+
" ██║ ██║╚██████╔╝███████╗██║ ╚████║ ██║ ███████╗██║ ██║███████║",
|
|
15
|
+
" ╚═╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝",
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
// Compact single-line wordmark for narrow terminals.
|
|
19
|
+
const WORDMARK_COMPACT = "▞▖ AGENTLAS";
|
|
20
|
+
|
|
21
|
+
// Brand gradient (emerald → green → lime → blue) applied left-to-right across the wordmark.
|
|
22
|
+
const GRADIENT = [
|
|
23
|
+
[110, 231, 183],
|
|
24
|
+
[52, 211, 153],
|
|
25
|
+
[16, 185, 129],
|
|
26
|
+
[45, 212, 191],
|
|
27
|
+
[56, 189, 248],
|
|
28
|
+
[147, 197, 253],
|
|
15
29
|
];
|
|
16
30
|
|
|
17
31
|
function readVersion() {
|
|
@@ -28,16 +42,30 @@ function shorten(p) {
|
|
|
28
42
|
return p.startsWith(home) ? "~" + p.slice(home.length) : p;
|
|
29
43
|
}
|
|
30
44
|
|
|
31
|
-
//
|
|
45
|
+
// AGENTLAS wordmark, per-column brand gradient. Falls back to plain / compact.
|
|
32
46
|
function renderMascot(ui) {
|
|
33
47
|
const c = ui.c;
|
|
48
|
+
const cols = (ui.out && ui.out.columns) || 80;
|
|
34
49
|
if (!ui.enabled) {
|
|
35
|
-
ui.line("
|
|
50
|
+
ui.line(" AGENTLAS");
|
|
36
51
|
return;
|
|
37
52
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
ui.line("
|
|
53
|
+
// Narrow terminal → compact wordmark.
|
|
54
|
+
if (cols < 72) {
|
|
55
|
+
ui.line(" " + c.bold(c.emerald(WORDMARK_COMPACT)));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const g = (rgb, s) => `\x1b[1;38;2;${rgb[0]};${rgb[1]};${rgb[2]}m${s}\x1b[0m`;
|
|
59
|
+
for (const rowStr of WORDMARK) {
|
|
60
|
+
let outLine = "";
|
|
61
|
+
const n = rowStr.length || 1;
|
|
62
|
+
for (let i = 0; i < rowStr.length; i++) {
|
|
63
|
+
const ch = rowStr[i];
|
|
64
|
+
if (ch === " ") { outLine += " "; continue; }
|
|
65
|
+
const idx = Math.min(GRADIENT.length - 1, Math.floor((i / n) * GRADIENT.length));
|
|
66
|
+
outLine += g(GRADIENT[idx], ch);
|
|
67
|
+
}
|
|
68
|
+
ui.line(outLine);
|
|
41
69
|
}
|
|
42
70
|
}
|
|
43
71
|
|
|
@@ -70,10 +98,13 @@ function renderStatusCard(ctx, opts = {}) {
|
|
|
70
98
|
const runtime = ctx.runtimeLabel || "(not configured)";
|
|
71
99
|
const cwd = ctx.cwd ? shorten(ctx.cwd) : process.cwd();
|
|
72
100
|
|
|
101
|
+
ui.line("");
|
|
102
|
+
if (!opts.noWordmark) {
|
|
103
|
+
renderMascot(ui);
|
|
104
|
+
ui.line(" " + c.dim("the operating system for agents") + (version ? c.faint(" v" + version) : ""));
|
|
105
|
+
}
|
|
73
106
|
ui.line("");
|
|
74
107
|
ui.line(c.faint("╭" + "─".repeat(width - 2) + "╮"));
|
|
75
|
-
row(ui, width, `>_ Agentlas${version ? " (v" + version + ")" : ""}`);
|
|
76
|
-
row(ui, width, "");
|
|
77
108
|
row(ui, width, `model: ${runtime}`);
|
|
78
109
|
row(ui, width, `agent: ${subject}`);
|
|
79
110
|
row(ui, width, `directory: ${cwd}`);
|
|
@@ -100,9 +131,9 @@ function renderBanner(ctx) {
|
|
|
100
131
|
ctx.ui.line("");
|
|
101
132
|
}
|
|
102
133
|
|
|
103
|
-
// runtime · subject · permission · working folder
|
|
134
|
+
// runtime · subject · permission · working folder (no wordmark — used for /status).
|
|
104
135
|
function renderStatus(ctx) {
|
|
105
|
-
renderStatusCard(ctx, { noTip: true });
|
|
136
|
+
renderStatusCard(ctx, { noTip: true, noWordmark: true });
|
|
106
137
|
}
|
|
107
138
|
|
|
108
|
-
module.exports = { renderBanner, renderStatus, renderMascot, readVersion, shorten,
|
|
139
|
+
module.exports = { renderBanner, renderStatus, renderMascot, readVersion, shorten, WORDMARK, fit };
|
|
@@ -29,12 +29,23 @@ function extractHosts(error) {
|
|
|
29
29
|
return [...hosts];
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
/**
|
|
32
|
+
/** 에러 텍스트에서 config.toml 스키마 위반이 지목한 mcp_servers 이름을 뽑는다. */
|
|
33
|
+
function extractBadMcpServer(error) {
|
|
34
|
+
// 예: Error loading config.toml: url is not supported for stdio in "mcp_servers.agentlas"
|
|
35
|
+
const m = /mcp_servers\.([a-z0-9_.-]+)/i.exec(error || "");
|
|
36
|
+
return m ? m[1] : null;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** kind: mcp-oauth-unauthenticated | codex-config-invalid | timeout | cli-exit | unknown (데스크탑 TS와 동일 규칙) */
|
|
33
40
|
function classifyFailure(error) {
|
|
34
41
|
const text = error || "";
|
|
35
42
|
if (/authrequired|invalid_token|oauth-protected-resource|www_authenticate/i.test(text)) {
|
|
36
43
|
return { kind: "mcp-oauth-unauthenticated", hosts: extractHosts(text) };
|
|
37
44
|
}
|
|
45
|
+
// codex config.toml 파싱 실패(예: stdio 서버에 url 키) → CLI가 아예 기동 못 함.
|
|
46
|
+
if (/error loading config\.toml|url is not supported for stdio|invalid config/i.test(text)) {
|
|
47
|
+
return { kind: "codex-config-invalid", hosts: [], badServer: extractBadMcpServer(text) };
|
|
48
|
+
}
|
|
38
49
|
if (/no response for \d+s|auto-aborted/i.test(text)) return { kind: "timeout", hosts: [] };
|
|
39
50
|
if (/CLI exit \d+|exited with code [1-9]/i.test(text)) return { kind: "cli-exit", hosts: extractHosts(text) };
|
|
40
51
|
return { kind: "unknown", hosts: [] };
|
|
@@ -120,9 +131,21 @@ function disableCodexPlugin(pluginKey) {
|
|
|
120
131
|
* 데스크탑 runtime-doctor.ts 의 runRuntimeDoctor 와 동일 계약.
|
|
121
132
|
*/
|
|
122
133
|
function runRuntimeDoctor(errorMessage) {
|
|
123
|
-
const { kind, hosts } = classifyFailure(errorMessage);
|
|
134
|
+
const { kind, hosts, badServer } = classifyFailure(errorMessage);
|
|
124
135
|
const actions = [];
|
|
125
136
|
|
|
137
|
+
if (kind === "codex-config-invalid") {
|
|
138
|
+
// 진단만 한다(자동 수리 안 함): 원격 MCP 항목이라 안전한 무손실 수리가 없고,
|
|
139
|
+
// 사용자가 어느 항목을 어떻게 고칠지 알아야 한다. 명확한 조치를 안내한다.
|
|
140
|
+
const where = badServer ? `[mcp_servers.${badServer}]` : "일부 [mcp_servers.*] 항목";
|
|
141
|
+
return {
|
|
142
|
+
kind,
|
|
143
|
+
summary: `codex의 ~/.codex/config.toml ${where} 이(가) 잘못돼 codex가 기동하지 못합니다(예: stdio 서버에 url 키). 다른 런타임(--runtime claude-code)으로 우회하거나 그 항목을 고치세요.`,
|
|
144
|
+
repaired: false,
|
|
145
|
+
actions,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
126
149
|
if (kind === "mcp-oauth-unauthenticated") {
|
|
127
150
|
const hitList = findOauthPluginsByHost(hosts);
|
|
128
151
|
let repairedAny = false;
|
package/engine/agentlas-i18n.cjs
CHANGED
|
@@ -107,6 +107,7 @@ const STRINGS = {
|
|
|
107
107
|
"help.setup": "run language, runtime, and permission setup again",
|
|
108
108
|
"help.cwd": "show or change the working folder",
|
|
109
109
|
"help.memory": "show the memory being injected",
|
|
110
|
+
"help.careerGraph": "show/add source refs for the Career Graph routing index",
|
|
110
111
|
"help.ontology": "turn on/list/add project ontology sources with short natural commands",
|
|
111
112
|
"help.side": "ask a side question without saving it to chat context",
|
|
112
113
|
"help.status": "show model/runtime, agent, permission, and directory",
|
|
@@ -119,6 +120,11 @@ const STRINGS = {
|
|
|
119
120
|
"help.build": "build/repair/package an agent or team (Hephaestus)",
|
|
120
121
|
"help.route": "preview which agent/pipeline would take a request",
|
|
121
122
|
"help.research": "run the Research Engine (search/gather/read)",
|
|
123
|
+
"help.search": "discover agents in the Hub",
|
|
124
|
+
"help.install": "install an agent from the Hub by slug",
|
|
125
|
+
"help.network": "decompose a request into an A2A task force",
|
|
126
|
+
"help.browser": "real browser execution hardpoint",
|
|
127
|
+
"help.connect": "wire Telegram / platforms to an agent team",
|
|
122
128
|
"help.swarm": "fan out an emergent agent swarm on a goal",
|
|
123
129
|
"help.doctor": "check runtimes and data",
|
|
124
130
|
"help.compact": "drop older transcript turns and keep the latest context",
|
|
@@ -252,6 +258,7 @@ const STRINGS = {
|
|
|
252
258
|
"help.setup": "언어·런타임·권한 설정 다시 실행",
|
|
253
259
|
"help.cwd": "작업 폴더 보기/변경",
|
|
254
260
|
"help.memory": "주입되는 메모리 보기",
|
|
261
|
+
"help.careerGraph": "Career Graph 라우팅 색인의 원본 경로 보기/등록",
|
|
255
262
|
"help.ontology": "짧은 자연어로 프로젝트 온톨로지 켜기/목록/자료 등록",
|
|
256
263
|
"help.side": "메인 대화 맥락에 저장하지 않는 사이드 질문",
|
|
257
264
|
"help.status": "모델/런타임, 에이전트, 권한, 작업 폴더 보기",
|
|
@@ -264,6 +271,11 @@ const STRINGS = {
|
|
|
264
271
|
"help.build": "에이전트/팀 빌드·수리·패키징 (Hephaestus)",
|
|
265
272
|
"help.route": "요청이 어떤 에이전트로 라우팅되는지 미리보기",
|
|
266
273
|
"help.research": "Research Engine 실행 (search/gather/read)",
|
|
274
|
+
"help.search": "Hub에서 에이전트 발견",
|
|
275
|
+
"help.install": "slug로 Hub 에이전트 설치",
|
|
276
|
+
"help.network": "요청을 A2A 태스크포스로 분해",
|
|
277
|
+
"help.browser": "실제 브라우저 실행 하드포인트",
|
|
278
|
+
"help.connect": "Telegram/플랫폼을 에이전트 팀에 연결",
|
|
267
279
|
"help.swarm": "목표에 emergent 에이전트 스웜 전개",
|
|
268
280
|
"help.doctor": "런타임/데이터 점검",
|
|
269
281
|
"help.compact": "오래된 대화 맥락을 줄이고 최근 맥락 유지",
|
|
@@ -75,6 +75,7 @@ const SLASH_COMMAND_META = [
|
|
|
75
75
|
{ command: "/help", description: "Show Agentlas terminal commands", category: "Help", usage: "/help", detail: "Open the command reference, shortcuts, and common flows." },
|
|
76
76
|
{ command: "/status", description: "Show model/runtime, agent, permission, and directory", category: "Session", usage: "/status", detail: "Print the current runtime, active agent or company, permission level, and cwd." },
|
|
77
77
|
{ command: "/skills", description: "List available Agentlas terminal skills", category: "Discovery", usage: "/skills", detail: "Show the slash-command skills Agentlas can run inside this terminal." },
|
|
78
|
+
{ command: "/career-graph", description: "Show or add Career Graph source refs", category: "Knowledge", usage: "/career-graph add ./docs", detail: "Career Graph routes agents to source Markdown, JSONL ledgers, sitemap, and code map before broad scans.", examples: ["/career-graph status", "/career-graph add ./docs", "/career-graph open"] },
|
|
78
79
|
{ command: "/ontology", description: "Turn on, list, or add project ontology sources", category: "Knowledge", usage: "/ontology add ./docs", detail: "Also understands natural text like /ontology use ./docs as company knowledge.", examples: ["/ontology list", "/ontology use ./docs as company knowledge", "/ontology open"] },
|
|
79
80
|
{ command: "/agents", description: "List installed agents", category: "Routing", usage: "/agents", detail: "Show local agents and their routed runtime." },
|
|
80
81
|
{ command: "/team", description: "View or pin each agent runtime", category: "Routing", usage: "/team <agent> <runtime|auto>", detail: "Pin one agent to claude-code, codex, gemini, or automatic routing." },
|
|
@@ -107,6 +108,11 @@ const SLASH_COMMAND_META = [
|
|
|
107
108
|
{ command: "/build", description: "Build/repair/package an agent or team (Hephaestus)", category: "Engine", usage: "/build <what to build>", detail: "Runs Hephaestus hep-build natively — deep interview, scaffolding, packaging." },
|
|
108
109
|
{ command: "/route", description: "Preview which agent/pipeline would take a request", category: "Engine", usage: "/route <request>", detail: "Runs the Hephaestus router without executing — shows the selected agent, candidates, and reasons." },
|
|
109
110
|
{ command: "/research", description: "Run the Hephaestus Research Engine", category: "Engine", usage: "/research search \"query\"", detail: "status|gather|search|read|plan — evidence-grade web research from the terminal." },
|
|
111
|
+
{ command: "/search", description: "Discover agents in the Hub", category: "Hub", usage: "/search <what you need>", detail: "Search the Agentlas Hub + local for an agent that fits the task (hep-search)." },
|
|
112
|
+
{ command: "/install", description: "Install an agent from the Hub by slug", category: "Hub", usage: "/install <slug>", detail: "Install a marketplace agent into this terminal (hep-cloud)." },
|
|
113
|
+
{ command: "/network", description: "Decompose a request into an A2A task force", category: "Engine", usage: "/network <request>", detail: "Runs Hephaestus hep-network — splits a composite request across agents.", aliases: ["/taskforce"] },
|
|
114
|
+
{ command: "/browser", description: "Real browser execution hardpoint", category: "Engine", usage: "/browser [sub]", detail: "Runs the Agentlas browser hardpoint (hep-browser)." },
|
|
115
|
+
{ command: "/connect", description: "Wire Telegram / platforms to an agent team", category: "Hub", usage: "/connect", detail: "Runs Hephaestus hep-connect for platform integration." },
|
|
110
116
|
{ command: "/doctor", description: "Check runtimes and local data", category: "Health", usage: "/doctor", detail: "Run local checks for runtimes, data, credentials, and setup." },
|
|
111
117
|
{ command: "/exit", description: "Quit Agentlas", category: "Session", usage: "/exit", detail: "Close the terminal session.", aliases: ["/quit"] },
|
|
112
118
|
];
|
|
@@ -406,6 +412,7 @@ function makeCompleter(ctx) {
|
|
|
406
412
|
return [uniqStartsWith(RUNTIME_SPECS.concat(["auto"]), last), last];
|
|
407
413
|
case "/cwd":
|
|
408
414
|
case "/import":
|
|
415
|
+
case "/career-graph":
|
|
409
416
|
case "/ontology":
|
|
410
417
|
return [completePath(last, getCwd(), ""), last];
|
|
411
418
|
default:
|
|
@@ -23,6 +23,13 @@ const { Ui } = require("./agentlas-ui.cjs");
|
|
|
23
23
|
const SWARM_MAX_TASKS = 24;
|
|
24
24
|
const SWARM_SPAWN_PER_TURN = 12;
|
|
25
25
|
|
|
26
|
+
// Agentlas-OS/Hephaestus 내부 시스템 에이전트(마켓 제품 아님) — 검색/목록에서 숨긴다.
|
|
27
|
+
// 데스크탑 electron/agents/hired-agents.ts isInternalAgentSlug 와 규칙 동일.
|
|
28
|
+
function isInternalAgentSlug(slug) {
|
|
29
|
+
const s = String(slug || "").toLowerCase();
|
|
30
|
+
return /^researcher-\d+/.test(s) || s === "research-intelligence-desk" || s.startsWith("hephaestus-");
|
|
31
|
+
}
|
|
32
|
+
|
|
26
33
|
function create(deps) {
|
|
27
34
|
const D = deps;
|
|
28
35
|
|
|
@@ -56,6 +63,35 @@ function create(deps) {
|
|
|
56
63
|
return null;
|
|
57
64
|
}
|
|
58
65
|
|
|
66
|
+
function careerGraphRuntime() {
|
|
67
|
+
const binCandidates = [
|
|
68
|
+
process.env.HEPHAESTUS_CAREER_GRAPH_BIN,
|
|
69
|
+
process.env.HEPHAESTUS_BIN ? path.join(path.dirname(process.env.HEPHAESTUS_BIN), "career-graph") : null,
|
|
70
|
+
path.join(os.homedir(), ".agentlas", "runtime", "current", "bin", "career-graph"),
|
|
71
|
+
];
|
|
72
|
+
for (const c of binCandidates) {
|
|
73
|
+
try {
|
|
74
|
+
if (c && fs.existsSync(c)) {
|
|
75
|
+
fs.accessSync(c, fs.constants.X_OK);
|
|
76
|
+
return { kind: "bin", exec: c };
|
|
77
|
+
}
|
|
78
|
+
} catch { /* 다음 후보 */ }
|
|
79
|
+
}
|
|
80
|
+
const roots = [
|
|
81
|
+
process.env.HEPHAESTUS_RUNTIME_ROOT,
|
|
82
|
+
path.join(os.homedir(), ".agentlas", "runtime", "current"),
|
|
83
|
+
];
|
|
84
|
+
if (process.resourcesPath) roots.push(path.join(process.resourcesPath, "Hephaestus"));
|
|
85
|
+
if (process.platform === "darwin") roots.push("/Applications/Agentlas.app/Contents/Resources/Hephaestus");
|
|
86
|
+
roots.push(path.resolve(__dirname, "..", "..", "agentlas_desktop", "Hephaestus"));
|
|
87
|
+
for (const root of roots) {
|
|
88
|
+
try {
|
|
89
|
+
if (root && fs.existsSync(path.join(root, "career_graph", "__main__.py"))) return { kind: "python", root };
|
|
90
|
+
} catch { /* 다음 후보 */ }
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
|
|
59
95
|
const PY_BOOTSTRAP =
|
|
60
96
|
"import os, runpy, sys; " +
|
|
61
97
|
'cwd=os.getcwd(); root=os.environ["HEPHAESTUS_RUNTIME_ROOT"]; ' +
|
|
@@ -189,17 +225,28 @@ function create(deps) {
|
|
|
189
225
|
// ── Hephaestus 네이티브 패스스루 — 엔진 전 기능을 터미널 1급으로 노출 ──
|
|
190
226
|
// stdio inherit 로 돌려 색/프롬프트/스트리밍이 네이티브 그대로 나온다.
|
|
191
227
|
function runHephaestusInteractive(args, opts = {}) {
|
|
192
|
-
const
|
|
228
|
+
const isCareerGraph = args[0] === "career-graph" || args[0] === "career_graph";
|
|
229
|
+
const found = isCareerGraph ? careerGraphRuntime() : hephaestusBin();
|
|
193
230
|
if (!found) {
|
|
194
|
-
process.stderr.write(
|
|
195
|
-
|
|
231
|
+
process.stderr.write(
|
|
232
|
+
isCareerGraph
|
|
233
|
+
? "Career Graph 런타임이 없습니다 — 최신 Agentlas OS / Hephaestus 설치 후 다시 시도하세요.\n"
|
|
234
|
+
: "Hephaestus 런타임이 없습니다 — 데스크탑 앱 설치 또는 Hephaestus 인스톨러 실행 후 다시 시도하세요.\n",
|
|
235
|
+
);
|
|
236
|
+
process.stderr.write(
|
|
237
|
+
isCareerGraph
|
|
238
|
+
? "설치 또는 지정: HEPHAESTUS_CAREER_GRAPH_BIN=<경로> 또는 HEPHAESTUS_RUNTIME_ROOT=<경로>\n"
|
|
239
|
+
: "설치: https://agentlas.cloud · 또는 HEPHAESTUS_BIN=<경로> 지정\n",
|
|
240
|
+
);
|
|
196
241
|
return Promise.resolve(1);
|
|
197
242
|
}
|
|
198
243
|
const cwd = opts.cwd || D.runCwd();
|
|
244
|
+
const moduleName = found.kind === "python" && isCareerGraph ? "career_graph" : "agentlas_cloud";
|
|
245
|
+
const moduleArgs = moduleName === "career_graph" ? args.slice(1) : args;
|
|
199
246
|
const child =
|
|
200
247
|
found.kind === "bin"
|
|
201
|
-
? spawn(found.exec, args, { cwd, stdio: "inherit" })
|
|
202
|
-
: spawn("python3", ["-c", PY_BOOTSTRAP,
|
|
248
|
+
? spawn(found.exec, isCareerGraph ? args.slice(1) : args, { cwd, stdio: "inherit" })
|
|
249
|
+
: spawn("python3", ["-c", PY_BOOTSTRAP, moduleName, ...moduleArgs], {
|
|
203
250
|
cwd,
|
|
204
251
|
stdio: "inherit",
|
|
205
252
|
env: { ...process.env, HEPHAESTUS_RUNTIME_ROOT: found.root },
|
|
@@ -958,7 +1005,8 @@ function create(deps) {
|
|
|
958
1005
|
headers,
|
|
959
1006
|
body: JSON.stringify({
|
|
960
1007
|
method: "marketplace.search_agents",
|
|
961
|
-
|
|
1008
|
+
// Hub는 파라미터 이름이 `q` — `query`만 보내면 무시하고 기본 목록을 준다(데스크탑 mcp-source.ts와 동일하게 둘 다 전송).
|
|
1009
|
+
params: { name: "marketplace.search_agents", arguments: { q: query, query, limit } },
|
|
962
1010
|
}),
|
|
963
1011
|
});
|
|
964
1012
|
} catch (e) {
|
|
@@ -968,7 +1016,9 @@ function create(deps) {
|
|
|
968
1016
|
const json = await resp.json();
|
|
969
1017
|
if (json.error) return D.fail(json.error.message || "marketplace error");
|
|
970
1018
|
const result = json.result || {};
|
|
971
|
-
const
|
|
1019
|
+
const rawItems = result.results || result.agents || result.items || (Array.isArray(result) ? result : null);
|
|
1020
|
+
// 엔진 내부 에이전트(researcher-<n>, research-intelligence-desk, hephaestus-*)는 제품이 아니므로 숨긴다.
|
|
1021
|
+
const items = Array.isArray(rawItems) ? rawItems.filter((it) => !isInternalAgentSlug(it && (it.slug || it.id))) : rawItems;
|
|
972
1022
|
if (!Array.isArray(items) || !items.length) {
|
|
973
1023
|
D.out(`검색 결과 없음: "${query}"`);
|
|
974
1024
|
return;
|
|
@@ -981,7 +1031,7 @@ function create(deps) {
|
|
|
981
1031
|
D.out(`${String(slug).padEnd(34).slice(0, 34)} ${String(name).slice(0, 26).padEnd(27)} ${String(kind).padEnd(14)} ${String(tagline).slice(0, 60)}`);
|
|
982
1032
|
}
|
|
983
1033
|
D.out("");
|
|
984
|
-
D.out("설치: agentlas
|
|
1034
|
+
D.out("설치: agentlas install <slug>");
|
|
985
1035
|
}
|
|
986
1036
|
|
|
987
1037
|
return {
|
package/engine/agentlas-repl.cjs
CHANGED
|
@@ -537,7 +537,7 @@ function startRepl(opts) {
|
|
|
537
537
|
const fmt = (e) => {
|
|
538
538
|
const bits = [e.turns + (e.turns === 1 ? " turn" : " turns")];
|
|
539
539
|
if (e.in || e.out) bits.push(e.in + "→" + e.out + " tok");
|
|
540
|
-
|
|
540
|
+
// 달러 비용 미표시 — 토큰 수만.
|
|
541
541
|
if (e.ms) bits.push((e.ms / 1000).toFixed(1) + "s");
|
|
542
542
|
return bits.join(" · ");
|
|
543
543
|
};
|
|
@@ -722,6 +722,37 @@ function startRepl(opts) {
|
|
|
722
722
|
await H.hepRun(["research", ...arg.split(/\s+/)], { cwd: state.cwd });
|
|
723
723
|
return true;
|
|
724
724
|
}
|
|
725
|
+
case "search": {
|
|
726
|
+
if (!arg) return ui.warn("usage: /search <할 일>"), true;
|
|
727
|
+
if (H.cloudSearch) await H.cloudSearch(db, [arg]);
|
|
728
|
+
else await H.hepRun(["hep-search", arg], { cwd: state.cwd });
|
|
729
|
+
return true;
|
|
730
|
+
}
|
|
731
|
+
case "install": {
|
|
732
|
+
if (!arg) return ui.warn("usage: /install <slug> (/search 로 먼저 찾으세요)"), true;
|
|
733
|
+
if (H.cloudInstall) {
|
|
734
|
+
try { const r = await H.cloudInstall(db, arg.trim()); ui.ok((r && r.name) ? `설치됨: ${r.name}` : `설치됨: ${arg.trim()}`); }
|
|
735
|
+
catch (e) { ui.error((e && e.message) || String(e)); }
|
|
736
|
+
} else ui.warn("설치 기능을 사용할 수 없습니다.");
|
|
737
|
+
return true;
|
|
738
|
+
}
|
|
739
|
+
case "network":
|
|
740
|
+
case "taskforce": {
|
|
741
|
+
if (!arg) return ui.warn("usage: /network <요청> (A2A 태스크포스)"), true;
|
|
742
|
+
ui.line("");
|
|
743
|
+
await H.hepRun(["hep-network", arg, "--project", state.cwd, "--runtime", "terminal"], { cwd: state.cwd });
|
|
744
|
+
return true;
|
|
745
|
+
}
|
|
746
|
+
case "browser": {
|
|
747
|
+
ui.line("");
|
|
748
|
+
await H.hepRun(["hep-browser", ...(arg ? arg.split(/\s+/) : [])], { cwd: state.cwd });
|
|
749
|
+
return true;
|
|
750
|
+
}
|
|
751
|
+
case "connect": {
|
|
752
|
+
ui.line("");
|
|
753
|
+
await H.hepRun(["hep-connect", ...(arg ? arg.split(/\s+/) : [])], { cwd: state.cwd });
|
|
754
|
+
return true;
|
|
755
|
+
}
|
|
725
756
|
case "swarm": {
|
|
726
757
|
if (!arg) return ui.warn("usage: /swarm <goal> [--parallel N]"), true;
|
|
727
758
|
let goal = arg;
|
|
@@ -818,6 +849,18 @@ function startRepl(opts) {
|
|
|
818
849
|
}
|
|
819
850
|
return true;
|
|
820
851
|
}
|
|
852
|
+
case "career-graph":
|
|
853
|
+
case "graph": {
|
|
854
|
+
if (!H.careerGraphCommand) return ui.warn("career graph command unavailable"), true;
|
|
855
|
+
try {
|
|
856
|
+
const lines = H.careerGraphCommand(arg, { cwd: state.cwd, projectPath: state.projectPath });
|
|
857
|
+
ui.line("");
|
|
858
|
+
for (const item of lines || []) ui.line(" " + ui.c.text(String(item)));
|
|
859
|
+
} catch (e) {
|
|
860
|
+
ui.error((e && e.message) || String(e));
|
|
861
|
+
}
|
|
862
|
+
return true;
|
|
863
|
+
}
|
|
821
864
|
case "side":
|
|
822
865
|
case "btw":
|
|
823
866
|
if (!arg) return ui.warn(ui.t("sideUsage")), true;
|
|
@@ -1212,6 +1255,7 @@ function printHelp(ui) {
|
|
|
1212
1255
|
["/setup", ui.t("help.setup")],
|
|
1213
1256
|
["/cwd [path]", ui.t("help.cwd")],
|
|
1214
1257
|
["/memory", ui.t("help.memory")],
|
|
1258
|
+
["/career-graph [text]", ui.t("help.careerGraph")],
|
|
1215
1259
|
["/ontology [text]", ui.t("help.ontology")],
|
|
1216
1260
|
["/side <question>", ui.t("help.side")],
|
|
1217
1261
|
["/status", ui.t("help.status")],
|
|
@@ -1228,8 +1272,12 @@ function printHelp(ui) {
|
|
|
1228
1272
|
["/build <request>", ui.t("help.build")],
|
|
1229
1273
|
["/route <request>", ui.t("help.route")],
|
|
1230
1274
|
["/research <sub>", ui.t("help.research")],
|
|
1231
|
-
["/
|
|
1275
|
+
["/search <task>", ui.t("help.search")],
|
|
1232
1276
|
["/install <slug>", ui.t("help.install")],
|
|
1277
|
+
["/network <req>", ui.t("help.network")],
|
|
1278
|
+
["/browser", ui.t("help.browser")],
|
|
1279
|
+
["/connect", ui.t("help.connect")],
|
|
1280
|
+
["/marketplace", ui.t("help.market")],
|
|
1233
1281
|
["/clear", ui.t("help.clear")],
|
|
1234
1282
|
["/doctor", ui.t("help.doctor")],
|
|
1235
1283
|
["/keybindings", ui.t("help.keybindings")],
|
package/engine/agentlas-ui.cjs
CHANGED
|
@@ -252,7 +252,7 @@ class Ui {
|
|
|
252
252
|
if (usage.input_tokens != null || usage.output_tokens != null) {
|
|
253
253
|
bits.push(`${usage.input_tokens ?? "?"}→${usage.output_tokens ?? "?"} tok`);
|
|
254
254
|
}
|
|
255
|
-
|
|
255
|
+
// 달러 비용은 표시하지 않는다 — 토큰 수만 (사용자 결정 2026-07-09).
|
|
256
256
|
if (usage.duration_ms != null) bits.push(`${(usage.duration_ms / 1000).toFixed(1)}s`);
|
|
257
257
|
if (bits.length) this.line(this.c.faint(" " + bits.join(" · ")));
|
|
258
258
|
}
|
package/engine/agentlas.cjs
CHANGED
|
@@ -913,7 +913,7 @@ async function packageCloudAgentCli(db, root, opts) {
|
|
|
913
913
|
const routingCard = readCloudRoutingCardCli(rootPath);
|
|
914
914
|
if (routingCard.finding) scan.findings.push(routingCard.finding);
|
|
915
915
|
const name = cloudReadName(rootPath);
|
|
916
|
-
const slug = cloudSlug(opts.slug || name || path.basename(rootPath));
|
|
916
|
+
const slug = cloudSlug(opts.slug || cloudReadStableSlug(rootPath) || name || path.basename(rootPath));
|
|
917
917
|
const packageHash = cloudHashPackage(scan.included);
|
|
918
918
|
const manifest = {
|
|
919
919
|
version: "0.1",
|
|
@@ -1332,11 +1332,29 @@ function printCloudPackageResult(result) {
|
|
|
1332
1332
|
}
|
|
1333
1333
|
|
|
1334
1334
|
function cloudReadName(rootPath) {
|
|
1335
|
+
const manifest = cloudReadPackageJson(rootPath);
|
|
1336
|
+
const explicit = stringFirstCli(
|
|
1337
|
+
manifest.agentlas?.displayName,
|
|
1338
|
+
manifest.agentlas?.name,
|
|
1339
|
+
manifest.manifest?.name,
|
|
1340
|
+
manifest.agentCard?.name,
|
|
1341
|
+
manifest.routingCard?.name,
|
|
1342
|
+
);
|
|
1343
|
+
if (explicit) return explicit.replace(/\s+/g, " ").trim().slice(0, 80);
|
|
1335
1344
|
const text = cloudReadFirst(rootPath, ["agent.md", "AGENT.md", "README.md", "CLAUDE.md", "AGENTS.md"], 2000);
|
|
1336
1345
|
const heading = text.match(/^#\s+(.+)$/m);
|
|
1337
1346
|
return (heading ? heading[1] : path.basename(rootPath)).replace(/\s+/g, " ").trim().slice(0, 80);
|
|
1338
1347
|
}
|
|
1339
1348
|
function cloudReadTagline(rootPath) {
|
|
1349
|
+
const manifest = cloudReadPackageJson(rootPath);
|
|
1350
|
+
const explicit = stringFirstCli(
|
|
1351
|
+
manifest.agentlas?.summary,
|
|
1352
|
+
manifest.agentlas?.description,
|
|
1353
|
+
manifest.manifest?.description,
|
|
1354
|
+
manifest.agentCard?.summary,
|
|
1355
|
+
manifest.routingCard?.summary,
|
|
1356
|
+
);
|
|
1357
|
+
if (explicit) return explicit.replace(/\s+/g, " ").trim().slice(0, 160);
|
|
1340
1358
|
const text = cloudReadFirst(rootPath, ["README.md", "agent.md", "AGENT.md"], 3000);
|
|
1341
1359
|
for (const line of text.split(/\r?\n/)) {
|
|
1342
1360
|
const t = line.trim();
|
|
@@ -1344,6 +1362,32 @@ function cloudReadTagline(rootPath) {
|
|
|
1344
1362
|
}
|
|
1345
1363
|
return "Portable Agentlas cloud agent package.";
|
|
1346
1364
|
}
|
|
1365
|
+
function cloudReadStableSlug(rootPath) {
|
|
1366
|
+
const manifest = cloudReadPackageJson(rootPath);
|
|
1367
|
+
return stringFirstCli(
|
|
1368
|
+
manifest.agentlas?.slug,
|
|
1369
|
+
manifest.agentlas?.id,
|
|
1370
|
+
manifest.manifest?.package,
|
|
1371
|
+
manifest.manifest?.slug,
|
|
1372
|
+
manifest.agentCard?.slug,
|
|
1373
|
+
manifest.agentCard?.id,
|
|
1374
|
+
manifest.routingCard?.agent_card_ref?.slug,
|
|
1375
|
+
);
|
|
1376
|
+
}
|
|
1377
|
+
function cloudReadPackageJson(rootPath) {
|
|
1378
|
+
return {
|
|
1379
|
+
agentlas: readJsonObjectCli(path.join(rootPath, "agentlas.json"), {}),
|
|
1380
|
+
manifest: readJsonObjectCli(path.join(rootPath, "manifest.json"), {}),
|
|
1381
|
+
agentCard: readJsonObjectCli(path.join(rootPath, ".agentlas", "agent-card.json"), {}),
|
|
1382
|
+
routingCard: readJsonObjectCli(path.join(rootPath, ".agentlas", "routing-card.json"), {}),
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1385
|
+
function stringFirstCli(...values) {
|
|
1386
|
+
for (const value of values) {
|
|
1387
|
+
if (typeof value === "string" && value.trim()) return value.trim();
|
|
1388
|
+
}
|
|
1389
|
+
return "";
|
|
1390
|
+
}
|
|
1347
1391
|
function cloudReadFirst(rootPath, names, maxChars) {
|
|
1348
1392
|
for (const name of names) {
|
|
1349
1393
|
const file = path.join(rootPath, name);
|
|
@@ -1413,7 +1457,7 @@ function loadArch() {
|
|
|
1413
1457
|
try {
|
|
1414
1458
|
_arch = require("./architecture.data.json");
|
|
1415
1459
|
} catch {
|
|
1416
|
-
_arch = { version: "0", agents: [], emitterBlock: "", eventsHeading: "## Memory Events", memoryDir: ".agentlas", soulFile: "project-soul-memory.md", sitemapFile: "sitemap.json", logFile: "memory-log.jsonl", kinds: [], scopes: [] };
|
|
1460
|
+
_arch = { version: "0", agents: [], emitterBlock: "", eventsHeading: "## Memory Events", memoryDir: ".agentlas", soulFile: "project-soul-memory.md", sitemapFile: "sitemap.json", logFile: "memory-log.jsonl", careerGraphConfigFile: "career-graph.json", careerGraphSourceManifestFile: "career-graph-sources.json", careerGraphInboxDir: "career-graph-inbox", careerGraphDbFile: "career-graph.sqlite", kinds: [], scopes: [] };
|
|
1417
1461
|
}
|
|
1418
1462
|
return _arch;
|
|
1419
1463
|
}
|
|
@@ -1731,6 +1775,10 @@ function ensureProjectMemoryCli(projectPath, projectName) {
|
|
|
1731
1775
|
const ontologySourceManifestFile = arch.ontologySourceManifestFile || "ontology-sources.json";
|
|
1732
1776
|
const ontologyInboxDir = arch.ontologyInboxDir || "ontology-inbox";
|
|
1733
1777
|
const ontologyDbFile = arch.ontologyDbFile || "ontology-runtime.sqlite";
|
|
1778
|
+
const careerGraphConfigFile = arch.careerGraphConfigFile || "career-graph.json";
|
|
1779
|
+
const careerGraphSourceManifestFile = arch.careerGraphSourceManifestFile || "career-graph-sources.json";
|
|
1780
|
+
const careerGraphInboxDir = arch.careerGraphInboxDir || "career-graph-inbox";
|
|
1781
|
+
const careerGraphDbFile = arch.careerGraphDbFile || "career-graph.sqlite";
|
|
1734
1782
|
const superOntologyContractFile = arch.superOntologyContractFile || "super-ontology-contract.json";
|
|
1735
1783
|
const superOntologyOpenWorldCoverageFile =
|
|
1736
1784
|
arch.superOntologyOpenWorldCoverageFile || "super-ontology-open-world-coverage.json";
|
|
@@ -1876,6 +1924,38 @@ function ensureProjectMemoryCli(projectPath, projectName) {
|
|
|
1876
1924
|
sources: [],
|
|
1877
1925
|
}, null, 2), "utf8");
|
|
1878
1926
|
}
|
|
1927
|
+
const careerGraphInbox = path.join(dir, careerGraphInboxDir);
|
|
1928
|
+
if (!fs.existsSync(careerGraphInbox)) fs.mkdirSync(careerGraphInbox, { recursive: true });
|
|
1929
|
+
const careerGraphConfig = path.join(dir, careerGraphConfigFile);
|
|
1930
|
+
if (!fs.existsSync(careerGraphConfig)) {
|
|
1931
|
+
fs.writeFileSync(careerGraphConfig, JSON.stringify({
|
|
1932
|
+
schemaVersion: "1.0",
|
|
1933
|
+
kind: "agentlas-career-graph",
|
|
1934
|
+
state: "active",
|
|
1935
|
+
model: "ledger_first_derived_index",
|
|
1936
|
+
projectRoot: projectPath,
|
|
1937
|
+
projectName: name,
|
|
1938
|
+
dbPath: path.join(dir, careerGraphDbFile),
|
|
1939
|
+
inboxPath: careerGraphInbox,
|
|
1940
|
+
sourceManifest: path.join(dir, careerGraphSourceManifestFile),
|
|
1941
|
+
canonicalSourcePolicy: {
|
|
1942
|
+
sourceOfTruth: "markdown_jsonl_json",
|
|
1943
|
+
graphIsRebuildable: true,
|
|
1944
|
+
fallbackWhenStale: "read_canonical_files",
|
|
1945
|
+
neverScanHomeDirectory: true,
|
|
1946
|
+
neverScanSiblingProjects: true,
|
|
1947
|
+
},
|
|
1948
|
+
}, null, 2), "utf8");
|
|
1949
|
+
}
|
|
1950
|
+
const careerGraphSources = path.join(dir, careerGraphSourceManifestFile);
|
|
1951
|
+
if (!fs.existsSync(careerGraphSources)) {
|
|
1952
|
+
fs.writeFileSync(careerGraphSources, JSON.stringify({
|
|
1953
|
+
schemaVersion: "1.0",
|
|
1954
|
+
kind: "agentlas-career-graph-source-manifest",
|
|
1955
|
+
projectRoot: projectPath,
|
|
1956
|
+
sources: [],
|
|
1957
|
+
}, null, 2), "utf8");
|
|
1958
|
+
}
|
|
1879
1959
|
for (const fileName of [skillTrialsFile, curatorDecisionsFile]) {
|
|
1880
1960
|
const filePath = path.join(dir, fileName);
|
|
1881
1961
|
if (!fs.existsSync(filePath)) fs.writeFileSync(filePath, "", "utf8");
|
|
@@ -5465,6 +5545,182 @@ function runOntologyNaturalCli(text, opts) {
|
|
|
5465
5545
|
return runOntologyCli(parseOntologyNaturalArgsCli(text, cwd), { ...(opts || {}), cwd });
|
|
5466
5546
|
}
|
|
5467
5547
|
|
|
5548
|
+
function careerGraphPathsForCli(projectPath) {
|
|
5549
|
+
const arch = loadArch();
|
|
5550
|
+
const root = path.resolve(projectPath || process.cwd());
|
|
5551
|
+
const memoryDir = path.join(root, arch.memoryDir || ".agentlas");
|
|
5552
|
+
return {
|
|
5553
|
+
root,
|
|
5554
|
+
memoryDir,
|
|
5555
|
+
configPath: path.join(memoryDir, arch.careerGraphConfigFile || "career-graph.json"),
|
|
5556
|
+
sourceManifestPath: path.join(memoryDir, arch.careerGraphSourceManifestFile || "career-graph-sources.json"),
|
|
5557
|
+
inboxPath: path.join(memoryDir, arch.careerGraphInboxDir || "career-graph-inbox"),
|
|
5558
|
+
dbPath: path.join(memoryDir, arch.careerGraphDbFile || "career-graph.sqlite"),
|
|
5559
|
+
};
|
|
5560
|
+
}
|
|
5561
|
+
|
|
5562
|
+
function careerGraphSourceManifestSkeletonCli(root) {
|
|
5563
|
+
return {
|
|
5564
|
+
schemaVersion: "1.0",
|
|
5565
|
+
kind: "agentlas-career-graph-source-manifest",
|
|
5566
|
+
projectRoot: root,
|
|
5567
|
+
sources: [],
|
|
5568
|
+
};
|
|
5569
|
+
}
|
|
5570
|
+
|
|
5571
|
+
function ensureCareerGraphCli(projectPath) {
|
|
5572
|
+
const paths = careerGraphPathsForCli(projectPath);
|
|
5573
|
+
ensureProjectMemoryCli(paths.root, path.basename(paths.root) || "Project");
|
|
5574
|
+
fs.mkdirSync(paths.inboxPath, { recursive: true });
|
|
5575
|
+
if (!fs.existsSync(paths.sourceManifestPath)) {
|
|
5576
|
+
writeJsonSafeCli(paths.sourceManifestPath, careerGraphSourceManifestSkeletonCli(paths.root));
|
|
5577
|
+
}
|
|
5578
|
+
return paths;
|
|
5579
|
+
}
|
|
5580
|
+
|
|
5581
|
+
function readCareerGraphSourcesCli(sourceManifestPath) {
|
|
5582
|
+
const manifest = readJsonSafeCli(sourceManifestPath, { sources: [] });
|
|
5583
|
+
return Array.isArray(manifest.sources) ? manifest.sources : [];
|
|
5584
|
+
}
|
|
5585
|
+
|
|
5586
|
+
function careerGraphUsageLinesCli() {
|
|
5587
|
+
return [
|
|
5588
|
+
"Career Graph commands:",
|
|
5589
|
+
" career-graph status show source-routing files and index state",
|
|
5590
|
+
" career-graph list list inbox files and registered source refs",
|
|
5591
|
+
" career-graph open open the project career graph inbox",
|
|
5592
|
+
" career-graph add ./docs register a folder as private source material",
|
|
5593
|
+
"",
|
|
5594
|
+
"Full graph index commands live in Agentlas OS / Hephaestus:",
|
|
5595
|
+
" hephaestus career-graph ingest --project .",
|
|
5596
|
+
" hephaestus career-graph query \"release failures\" --project .",
|
|
5597
|
+
" hephaestus career-graph verify --project .",
|
|
5598
|
+
"",
|
|
5599
|
+
"Safety: the graph is rebuildable. Markdown, JSONL ledgers, sitemap, and code map stay source of truth.",
|
|
5600
|
+
];
|
|
5601
|
+
}
|
|
5602
|
+
|
|
5603
|
+
function existingCareerGraphCanonicalRefsCli(root) {
|
|
5604
|
+
return [
|
|
5605
|
+
".agentlas/project-soul-memory.md",
|
|
5606
|
+
".agentlas/memory-log.jsonl",
|
|
5607
|
+
".agentlas/curator-decisions.jsonl",
|
|
5608
|
+
".agentlas/sitemap.json",
|
|
5609
|
+
".agentlas/code-map/project-map.json",
|
|
5610
|
+
".agentlas/ledgers/routing-decisions.jsonl",
|
|
5611
|
+
".agentlas/ledgers/executions.jsonl",
|
|
5612
|
+
".agentlas/ledgers/agent-evolution-proposals.jsonl",
|
|
5613
|
+
].filter((rel) => fs.existsSync(path.join(root, rel)));
|
|
5614
|
+
}
|
|
5615
|
+
|
|
5616
|
+
function formatCareerGraphStatusCli(paths) {
|
|
5617
|
+
const sources = readCareerGraphSourcesCli(paths.sourceManifestPath);
|
|
5618
|
+
const inbox = listOntologyInboxCli(paths.inboxPath);
|
|
5619
|
+
const canonical = existingCareerGraphCanonicalRefsCli(paths.root);
|
|
5620
|
+
const lines = [
|
|
5621
|
+
"Career Graph: active",
|
|
5622
|
+
` project: ${paths.root}`,
|
|
5623
|
+
` inbox: ${paths.inboxPath}`,
|
|
5624
|
+
` db: ${paths.dbPath}`,
|
|
5625
|
+
` index: ${fs.existsSync(paths.dbPath) ? "present" : "pending"}`,
|
|
5626
|
+
" policy: ledger_first_derived_index",
|
|
5627
|
+
" source of truth: Markdown / JSONL / JSON files",
|
|
5628
|
+
"",
|
|
5629
|
+
`Canonical source refs (${canonical.length}):`,
|
|
5630
|
+
];
|
|
5631
|
+
for (const rel of canonical) lines.push(` ${rel}`);
|
|
5632
|
+
if (!canonical.length) lines.push(" (none yet)");
|
|
5633
|
+
lines.push("", `Inbox (${inbox.length}):`);
|
|
5634
|
+
for (const item of inbox) lines.push(` ${item.supported ? "ok" : "!"} ${item.name} ${item.supported ? "supported" : "adapter pending"}`);
|
|
5635
|
+
if (!inbox.length) lines.push(" (empty)");
|
|
5636
|
+
lines.push("", `Registered source refs (${sources.length}):`);
|
|
5637
|
+
for (const source of sources) {
|
|
5638
|
+
const sourcePath = path.resolve(String(source.path || ""));
|
|
5639
|
+
lines.push(` ${fs.existsSync(sourcePath) ? "ok" : "!"} ${sourcePath} ${source.kind || "project"} / ${source.scope || "private"}`);
|
|
5640
|
+
}
|
|
5641
|
+
if (!sources.length) lines.push(" (none)");
|
|
5642
|
+
lines.push(
|
|
5643
|
+
"",
|
|
5644
|
+
"Build the derived index with Agentlas OS:",
|
|
5645
|
+
` hephaestus career-graph ingest --project ${JSON.stringify(paths.root)}`,
|
|
5646
|
+
);
|
|
5647
|
+
return lines;
|
|
5648
|
+
}
|
|
5649
|
+
|
|
5650
|
+
function registerCareerGraphSourceCli(paths, source, kind, scope, cwd) {
|
|
5651
|
+
if (!source) throw new Error("usage: career-graph add <path>");
|
|
5652
|
+
const sourcePath = resolveOntologyPathCli(source, cwd || paths.root);
|
|
5653
|
+
if (!fs.existsSync(sourcePath)) throw new Error(`source not found: ${sourcePath}`);
|
|
5654
|
+
const manifest = readJsonSafeCli(paths.sourceManifestPath, careerGraphSourceManifestSkeletonCli(paths.root));
|
|
5655
|
+
const nextSources = (Array.isArray(manifest.sources) ? manifest.sources : [])
|
|
5656
|
+
.filter((item) => path.resolve(String(item.path || "")) !== sourcePath);
|
|
5657
|
+
nextSources.push({ path: sourcePath, kind, scope, registeredAt: new Date().toISOString() });
|
|
5658
|
+
manifest.schemaVersion = "1.0";
|
|
5659
|
+
manifest.kind = "agentlas-career-graph-source-manifest";
|
|
5660
|
+
manifest.projectRoot = paths.root;
|
|
5661
|
+
manifest.sources = nextSources;
|
|
5662
|
+
writeJsonSafeCli(paths.sourceManifestPath, manifest);
|
|
5663
|
+
return [
|
|
5664
|
+
`Registered Career Graph source: ${sourcePath}`,
|
|
5665
|
+
` kind: ${kind}`,
|
|
5666
|
+
` scope: ${scope}`,
|
|
5667
|
+
" copy: no",
|
|
5668
|
+
" scan: only this registered folder, not home/sibling projects",
|
|
5669
|
+
];
|
|
5670
|
+
}
|
|
5671
|
+
|
|
5672
|
+
function runCareerGraphCli(args, opts) {
|
|
5673
|
+
opts = opts || {};
|
|
5674
|
+
const cwd = path.resolve(opts.cwd || process.cwd());
|
|
5675
|
+
const projectPath = path.resolve(opts.projectPath || cwd);
|
|
5676
|
+
const normalizedArgs = Array.isArray(args) ? args : [];
|
|
5677
|
+
const sub = normalizedArgs[0] || "status";
|
|
5678
|
+
const paths = ensureCareerGraphCli(projectPath);
|
|
5679
|
+
if (sub === "status" || sub === "list") {
|
|
5680
|
+
return formatCareerGraphStatusCli(paths);
|
|
5681
|
+
}
|
|
5682
|
+
if (sub === "open") {
|
|
5683
|
+
if (!opts.noOpen) openLocalPathCli(paths.inboxPath);
|
|
5684
|
+
return [`Opened Career Graph inbox: ${paths.inboxPath}`];
|
|
5685
|
+
}
|
|
5686
|
+
if (sub === "help" || sub === "--help" || sub === "-h") {
|
|
5687
|
+
return careerGraphUsageLinesCli();
|
|
5688
|
+
}
|
|
5689
|
+
if (sub === "add") {
|
|
5690
|
+
const flags = parseCloudFlags(normalizedArgs.slice(1));
|
|
5691
|
+
const source = flags._[0];
|
|
5692
|
+
const kind = inferOntologyKindCli(flags.kind || flags._[1], normalizedArgs.join(" "));
|
|
5693
|
+
const scope = inferOntologyScopeCli(flags.scope || flags._[2], normalizedArgs.join(" "), kind);
|
|
5694
|
+
return registerCareerGraphSourceCli(paths, source, kind, scope, cwd);
|
|
5695
|
+
}
|
|
5696
|
+
if (["ingest", "query", "verify", "trace"].includes(String(sub))) {
|
|
5697
|
+
return [
|
|
5698
|
+
"Career Graph index execution is provided by Agentlas OS / Hephaestus.",
|
|
5699
|
+
`Run: hephaestus career-graph ${normalizedArgs.join(" ")} --project ${JSON.stringify(paths.root)}`,
|
|
5700
|
+
];
|
|
5701
|
+
}
|
|
5702
|
+
return runCareerGraphCli(parseOntologyNaturalArgsCli(normalizedArgs.join(" "), cwd), opts);
|
|
5703
|
+
}
|
|
5704
|
+
|
|
5705
|
+
function runCareerGraphNaturalCli(text, opts) {
|
|
5706
|
+
const cwd = path.resolve((opts && opts.cwd) || process.cwd());
|
|
5707
|
+
return runCareerGraphCli(parseOntologyNaturalArgsCli(text, cwd), { ...(opts || {}), cwd });
|
|
5708
|
+
}
|
|
5709
|
+
|
|
5710
|
+
async function cmdCareerGraph(args) {
|
|
5711
|
+
const sub = String((args && args[0]) || "status");
|
|
5712
|
+
if (["ingest", "query", "verify", "trace", "public-card"].includes(sub)) {
|
|
5713
|
+
const code = await parity().runHephaestusInteractive(["career-graph", ...args], { cwd: process.cwd() });
|
|
5714
|
+
if (code !== 0) process.exitCode = code;
|
|
5715
|
+
return;
|
|
5716
|
+
}
|
|
5717
|
+
try {
|
|
5718
|
+
for (const line of runCareerGraphCli(args, { cwd: process.cwd(), projectPath: process.cwd() })) out(line);
|
|
5719
|
+
} catch (e) {
|
|
5720
|
+
fail((e && e.message) || String(e));
|
|
5721
|
+
}
|
|
5722
|
+
}
|
|
5723
|
+
|
|
5468
5724
|
function cmdOntology(args) {
|
|
5469
5725
|
try {
|
|
5470
5726
|
for (const line of runOntologyCli(args, { cwd: process.cwd(), projectPath: process.cwd() })) out(line);
|
|
@@ -6130,6 +6386,11 @@ function buildHelpers(db) {
|
|
|
6130
6386
|
stormRun: (db_, goal, ctx) => parity().stormRun(db_, goal, ctx),
|
|
6131
6387
|
swarmRun: (db_, goal, ctx) => parity().swarmRun(db_, goal, ctx),
|
|
6132
6388
|
hepRun: (args, opts) => parity().runHephaestusInteractive(args, opts),
|
|
6389
|
+
cloudSearch: (db_, args) => parity().cloudSearch(db_, args),
|
|
6390
|
+
careerGraphCommand: (text, ctx) => runCareerGraphNaturalCli(text, {
|
|
6391
|
+
cwd: (ctx && ctx.cwd) || projectCwd(),
|
|
6392
|
+
projectPath: (ctx && ctx.cwd) || projectCwd(),
|
|
6393
|
+
}),
|
|
6133
6394
|
ontologyCommand: (text, ctx) => runOntologyNaturalCli(text, {
|
|
6134
6395
|
cwd: (ctx && ctx.cwd) || projectCwd(),
|
|
6135
6396
|
projectPath: (ctx && ctx.cwd) || projectCwd(),
|
|
@@ -7300,56 +7561,65 @@ async function cmdOberon(args) {
|
|
|
7300
7561
|
}
|
|
7301
7562
|
|
|
7302
7563
|
function cmdHelp() {
|
|
7564
|
+
const H = (s) => `\n\x1b[1m${s}\x1b[0m`;
|
|
7565
|
+
const useColor = process.stdout.isTTY && process.env.NO_COLOR == null;
|
|
7566
|
+
const hdr = (s) => (useColor ? H(s) : "\n" + s);
|
|
7303
7567
|
out(
|
|
7304
7568
|
[
|
|
7305
|
-
"agentlas —
|
|
7569
|
+
"agentlas — the operating system for agents, in your terminal",
|
|
7306
7570
|
"",
|
|
7307
|
-
" agentlas
|
|
7308
|
-
" agentlas \"
|
|
7309
|
-
" agentlas <agent> jump straight into a chat with one agent",
|
|
7310
|
-
" open <agent> same as above (explicit)",
|
|
7311
|
-
" firm <firm> [cmd] delegate to a company's CEO (interactive if no cmd)",
|
|
7312
|
-
" run [agent] [prompt] one-shot — omit agent to auto-route (reads stdin if no prompt)",
|
|
7313
|
-
" import <path> import a local folder (agent or team)",
|
|
7314
|
-
" cd <agent> print the agent folder — cd \"$(agentlas cd seo)\" && claude",
|
|
7315
|
-
" list agents/companies + active runtime",
|
|
7316
|
-
" env shared env key names",
|
|
7317
|
-
" multimodal image/video/audio fallback providers",
|
|
7318
|
-
" oberon <sub> AI film render from the terminal (scaffold|render|list) — see: oberon help",
|
|
7319
|
-
" ontology project-local ontology status/list/add; inside REPL use /ontology",
|
|
7320
|
-
" storm <goal> Stormbreaker force-robust pipeline (route → verify → execute) [--research]",
|
|
7321
|
-
" swarm <goal> emergent agent swarm — parallel workers + blackboard + synthesizer [--parallel N]",
|
|
7322
|
-
" build \"<request>\" build/repair/package an agent or team (Hephaestus hep-build)",
|
|
7323
|
-
" route \"<request>\" routing preview — which agent/pipeline would take this",
|
|
7324
|
-
" research <sub> Research Engine: status|gather|search|read|plan …",
|
|
7325
|
-
" network <sub> local agent network: init|status|reindex|add-source …",
|
|
7326
|
-
" journal <sub> Stormbreaker run journal: status|verify|repair|gate",
|
|
7327
|
-
" call \"a,b\" \"<ctx>\" prepare named Hub/Cloud agents (hep-call)",
|
|
7328
|
-
" hep <sub…> full Hephaestus passthrough (wizard·security·cards·ao·plugins…)",
|
|
7329
|
-
" mcp installed MCP servers (shared with the app)",
|
|
7330
|
-
" chats [n] recent app/terminal chats",
|
|
7331
|
-
" automation <sub> list|add|on|off|remove|run <id>|runs|daemon — local runner included",
|
|
7332
|
-
" login | logout | whoami",
|
|
7333
|
-
" Agentlas Cloud sign-in (browser flow) — marketplace install/publish",
|
|
7334
|
-
" usage local usage summary (runs, messages, automations)",
|
|
7335
|
-
" telegram telegram binding status (pairing lives in the app)",
|
|
7336
|
-
" cloud wizard <path> create/repair agentlas.json for Cloud MCP calls",
|
|
7337
|
-
" cloud security scan <path>",
|
|
7338
|
-
" risk-screen an agent folder before run/publish",
|
|
7339
|
-
" cloud runtime bundle <path>",
|
|
7340
|
-
" compile manifest-based runtime bundle",
|
|
7341
|
-
" cloud field-test run local Cloud contract fixture test",
|
|
7342
|
-
" cloud package <path> package + static security review for Agentlas Cloud",
|
|
7343
|
-
" cloud publish <path> register after local review (submitter runtime only)",
|
|
7344
|
-
" cloud install <slug> download/install a cloud marketplace agent",
|
|
7345
|
-
" creds save ... save an issued key (project vault + project .env + project-scoped global env)",
|
|
7346
|
-
" creds file ... copy a credential file into signing/credentials and set an env path",
|
|
7347
|
-
" update check and install the latest Agentlas Desktop release",
|
|
7348
|
-
" doctor check runtimes and data",
|
|
7349
|
-
" setup re-run first-launch setup (language · runtime · permission)",
|
|
7350
|
-
" version print the Agentlas CLI version",
|
|
7571
|
+
" agentlas open the terminal (wordmark, then type a task)",
|
|
7572
|
+
" agentlas \"<task>\" auto-route to the best agent and run once",
|
|
7351
7573
|
"",
|
|
7352
|
-
"
|
|
7574
|
+
hdr("TALK & RUN"),
|
|
7575
|
+
" <agent> jump into a chat with one agent (e.g. agentlas seo)",
|
|
7576
|
+
" run [agent] [prompt] one-shot — omit agent to auto-route (reads stdin if no prompt)",
|
|
7577
|
+
" firm <firm> [cmd] delegate to a company's CEO (interactive if no cmd)",
|
|
7578
|
+
" chats [n] recent conversations · chat resume in REPL: /resume",
|
|
7579
|
+
"",
|
|
7580
|
+
hdr("AGENTS & HUB (Agentlas OS surface)"),
|
|
7581
|
+
" search \"<what you need>\" discover agents in the Hub + local (hep-search)",
|
|
7582
|
+
" install <slug> install an agent from the Hub (hep-cloud)",
|
|
7583
|
+
" build \"<request>\" build/repair/package an agent or team (hep-build)",
|
|
7584
|
+
" upload <path> package + publish an agent to the Hub (hep-upload)",
|
|
7585
|
+
" connect [<sub>] wire Telegram / platforms to an agent team (hep-connect)",
|
|
7586
|
+
" import <path> import a local agent/team folder",
|
|
7587
|
+
" list installed agents/companies + active runtime",
|
|
7588
|
+
"",
|
|
7589
|
+
hdr("EXECUTE"),
|
|
7590
|
+
" storm <goal> force-robust pipeline: route → verify → execute (Stormbreaker) [--research]",
|
|
7591
|
+
" swarm <goal> emergent agent swarm — parallel workers + synthesizer [--parallel N]",
|
|
7592
|
+
" network <request> decompose a request into an A2A task force (hep-network)",
|
|
7593
|
+
" call \"a,b\" \"<ctx>\" invoke named Hub/Cloud agents (hep-call)",
|
|
7594
|
+
" browser [<sub>] real browser execution hardpoint (hep-browser)",
|
|
7595
|
+
" route \"<request>\" routing preview — which agent/pipeline would take this",
|
|
7596
|
+
"",
|
|
7597
|
+
hdr("KNOWLEDGE & RESEARCH"),
|
|
7598
|
+
" research <sub> Research Engine: status|gather|search|read|plan",
|
|
7599
|
+
" career-graph <sub> source routing index: status|list|add",
|
|
7600
|
+
" ontology <sub> project knowledge: status|list|add (REPL: /ontology)",
|
|
7601
|
+
" journal <sub> Stormbreaker run journal: status|verify|repair|gate",
|
|
7602
|
+
"",
|
|
7603
|
+
hdr("ACCOUNT & OPS"),
|
|
7604
|
+
" login | logout | whoami Agentlas Cloud sign-in (browser flow)",
|
|
7605
|
+
" automation <sub> list|add|on|off|remove|run <id>|runs|daemon (local scheduler)",
|
|
7606
|
+
" creds <sub> · env credentials vault and shared env keys",
|
|
7607
|
+
" multimodal image/video/audio provider settings",
|
|
7608
|
+
" usage · telegram · mcp local usage · telegram bindings · MCP servers",
|
|
7609
|
+
" doctor check runtimes, data, credentials",
|
|
7610
|
+
" update check for a newer agentlas on npm",
|
|
7611
|
+
" setup re-run first-launch setup (language · runtime · permission)",
|
|
7612
|
+
" version print the Agentlas CLI version",
|
|
7613
|
+
"",
|
|
7614
|
+
hdr("ADVANCED"),
|
|
7615
|
+
" hep <sub…> full Hephaestus passthrough (wizard·security·cards·ao·plugins·meta-agent…)",
|
|
7616
|
+
" netadmin <sub> local network admin: init|status|reindex|bench|add-source",
|
|
7617
|
+
" cloud <sub> agent packaging: wizard|security|bundle|package|publish|field-test",
|
|
7618
|
+
" cd <agent> print the agent folder — cd \"$(agentlas cd seo)\" && claude",
|
|
7619
|
+
" oberon <sub> AI film render (scaffold|render|list)",
|
|
7620
|
+
"",
|
|
7621
|
+
"Options: --runtime claude-code|codex|gemini · --permission read|write|full (default write)",
|
|
7622
|
+
"In the REPL, type / for the command palette (/build /route /research /storm /swarm …).",
|
|
7353
7623
|
].join("\n"),
|
|
7354
7624
|
);
|
|
7355
7625
|
}
|
|
@@ -7429,6 +7699,10 @@ async function main() {
|
|
|
7429
7699
|
return cmdOberon(rest.slice(1));
|
|
7430
7700
|
case "ontology":
|
|
7431
7701
|
return cmdOntology(rest.slice(1));
|
|
7702
|
+
case "career-graph":
|
|
7703
|
+
case "career_graph":
|
|
7704
|
+
case "graph":
|
|
7705
|
+
return cmdCareerGraph(rest.slice(1));
|
|
7432
7706
|
case "cloud":
|
|
7433
7707
|
return cmdCloud(db, rest.slice(1), runtimeOverride);
|
|
7434
7708
|
case "creds":
|
|
@@ -7443,24 +7717,41 @@ async function main() {
|
|
|
7443
7717
|
case "hep":
|
|
7444
7718
|
case "hephaestus":
|
|
7445
7719
|
return parity().cmdHep(db, rest.slice(1));
|
|
7720
|
+
// ── Agentlas OS 정식 표면 (hep-*) 1급 노출 ──
|
|
7446
7721
|
case "build":
|
|
7447
|
-
// hep-build "<요청>" —
|
|
7722
|
+
// hep-build "<요청>" — 에이전트/팀 빌드 (Meta-Agent Factory)
|
|
7448
7723
|
return parity().cmdHep(db, rest.length > 1 ? ["hep-build", rest.slice(1).join(" ")] : ["hep-build"]);
|
|
7449
|
-
case "
|
|
7724
|
+
case "search": // hep-search — 에이전트 디렉터리 발견 (Hub + 로컬)
|
|
7725
|
+
if (!rest[1]) return fail('usage: agentlas search "<찾는 일>" [--limit 10]');
|
|
7726
|
+
return parity().cloudSearch(db, rest.slice(1));
|
|
7727
|
+
case "install": // hep-cloud import — slug로 에이전트 설치
|
|
7728
|
+
if (!rest[1]) return fail('usage: agentlas install <slug> (먼저 agentlas search "할 일" 로 찾으세요)');
|
|
7729
|
+
return cmdCloudInstall(db, rest[1]);
|
|
7730
|
+
case "upload": // hep-upload — 컴파일된 에이전트를 Hub로 배포 (경로 필요)
|
|
7731
|
+
if (!rest[1]) return fail("usage: agentlas upload <에이전트 폴더 경로> (패키징 후 Hub 배포)");
|
|
7732
|
+
return cmdCloud(db, ["publish", ...rest.slice(1)], runtimeOverride);
|
|
7733
|
+
case "connect": // hep-connect — Telegram 등 플랫폼 연결
|
|
7734
|
+
return parity().cmdHep(db, ["hep-connect", ...rest.slice(1)]);
|
|
7735
|
+
case "browser": // hep-browser — 실제 브라우저 실행 하드포인트
|
|
7736
|
+
return parity().cmdHep(db, ["hep-browser", ...rest.slice(1)]);
|
|
7737
|
+
case "call": // hep-call — 지정 에이전트 호출/준비
|
|
7738
|
+
return parity().cmdHep(db, ["hep-call", ...rest.slice(1)]);
|
|
7739
|
+
case "network": // hep-network — A2A 태스크포스 분해/스케줄
|
|
7740
|
+
case "taskforce":
|
|
7741
|
+
return parity().cmdHep(db, ["hep-network", ...rest.slice(1)]);
|
|
7742
|
+
case "route": // 라우팅 미리보기 (실행 없음)
|
|
7450
7743
|
return parity().cmdHep(
|
|
7451
7744
|
db,
|
|
7452
7745
|
rest.length > 1
|
|
7453
7746
|
? ["route", rest.slice(1).join(" "), "--project", runCwd(), "--runtime", "terminal"]
|
|
7454
7747
|
: ["route"],
|
|
7455
7748
|
);
|
|
7456
|
-
case "research":
|
|
7749
|
+
case "research": // Research Engine
|
|
7457
7750
|
return parity().cmdHep(db, ["research", ...rest.slice(1)]);
|
|
7458
|
-
case "
|
|
7751
|
+
case "netadmin": // 로컬 에이전트 네트워크 관리 (init|status|reindex|bench|add-source)
|
|
7459
7752
|
return parity().cmdHep(db, ["network", ...rest.slice(1)]);
|
|
7460
|
-
case "journal":
|
|
7753
|
+
case "journal": // Stormbreaker 런 저널
|
|
7461
7754
|
return parity().cmdHep(db, ["stormbreaker", "journal", ...rest.slice(1)]);
|
|
7462
|
-
case "call":
|
|
7463
|
-
return parity().cmdHep(db, ["hep-call", ...rest.slice(1)]);
|
|
7464
7755
|
case "mcp":
|
|
7465
7756
|
return parity().cmdMcp(db);
|
|
7466
7757
|
case "chats":
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.5.
|
|
2
|
+
"version": "1.5.35",
|
|
3
3
|
"emitterBlock": "## Memory (Agentlas curated memory)\n\nIf — and only if — this turn produced something durable (a decision, a stable fact,\na user preference, a risk, a reusable procedure), end your reply with a Memory Events\nblock. Emit nothing when nothing durable was learned.\n\nRules:\n- Never include secrets, credentials, API keys, raw logs, or full transcripts.\n- Real credential values may live only in local project .env/.env.local,\n ignored signing/ or credentials/ files, or a local keychain/vault. Memory\n Events may mention env names and local relative paths only.\n- For deploy, release, store, billing, auth, API, or cloud work, first read the\n project's .agentlas/local-credentials.map.json and the top\n \"Local Credential Index\" section of .agentlas/project-soul-memory.md\n before saying a credential is missing.\n- One event per durable item. Keep \"content\" to one or two sentences.\n- \"memory_kind\": fact | decision | preference | risk | procedure | hypothesis | evidence | deprecation | conflict\n- \"suggested_scope\": user_identity | team_memory | project (this folder) | agent_repo | session (temporary) | discard\n- \"agent_team\" is accepted only as a legacy alias for team_memory.\n- Add \"request_context\" when it improves future recall: user_intent, trigger_terms,\n cwd_at_request, target_project, target_path, cross_context, outcome.\n- Never put the raw user prompt or transcript in request_context.\n- Suggest a scope; the Memory Curator decides the final destination.\n\nFormat (omit entirely if empty):\n\n## Memory Events\n```json\n[\n {\n \"memory_kind\": \"decision\",\n \"content\": \"...\",\n \"suggested_scope\": \"project\",\n \"confidence\": \"high\",\n \"evidence_refs\": [],\n \"request_context\": {\n \"user_intent\": \"...\",\n \"trigger_terms\": [\"...\"],\n \"cwd_at_request\": null,\n \"target_project\": null,\n \"target_path\": null,\n \"cross_context\": false,\n \"outcome\": \"...\"\n }\n }\n]\n```",
|
|
4
4
|
"eventsHeading": "## Memory Events",
|
|
5
5
|
"memoryDir": ".agentlas",
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
"skillRegistryFile": "skill-registry.json",
|
|
15
15
|
"skillTrialsFile": "skill-trials.jsonl",
|
|
16
16
|
"curatorDecisionsFile": "curator-decisions.jsonl",
|
|
17
|
+
"careerGraphConfigFile": "career-graph.json",
|
|
18
|
+
"careerGraphSourceManifestFile": "career-graph-sources.json",
|
|
19
|
+
"careerGraphInboxDir": "career-graph-inbox",
|
|
20
|
+
"careerGraphDbFile": "career-graph.sqlite",
|
|
17
21
|
"superOntologyContractFile": "super-ontology-contract.json",
|
|
18
22
|
"superOntologyOpenWorldCoverageFile": "super-ontology-open-world-coverage.json",
|
|
19
23
|
"superOntologyConsensusCoordinationFile": "super-ontology-consensus-coordination.json",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentlas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "Agentlas agent terminal — chat with your installed AI agents and teams from the terminal, Claude Code style. Standalone: no desktop app required.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"agentlas": "bin/agentlas.cjs"
|
package/test/smoke.sh
CHANGED
|
@@ -25,6 +25,20 @@ check "where" node "$BIN" --where
|
|
|
25
25
|
check "version" node "$BIN" version
|
|
26
26
|
check "list" node "$BIN" list
|
|
27
27
|
check "doctor" node "$BIN" doctor
|
|
28
|
+
check "help" node "$BIN" help
|
|
29
|
+
check "usage" node "$BIN" usage
|
|
30
|
+
check "mcp" node "$BIN" mcp
|
|
31
|
+
check "chats" node "$BIN" chats
|
|
32
|
+
|
|
33
|
+
# Agentlas OS 표면: 무인자 호출은 usage를 내고 exit 1 (프롬프트 오라우팅 방지 확인)
|
|
34
|
+
guard() {
|
|
35
|
+
name="$1"; shift
|
|
36
|
+
if out="$("$@" 2>&1)"; then echo "FAIL $name (should exit non-zero)"; fail=$((fail + 1));
|
|
37
|
+
else echo "PASS $name"; pass=$((pass + 1)); fi
|
|
38
|
+
}
|
|
39
|
+
guard "guard-search" node "$BIN" search
|
|
40
|
+
guard "guard-install" node "$BIN" install
|
|
41
|
+
guard "guard-upload" node "$BIN" upload
|
|
28
42
|
|
|
29
43
|
# 신선 환경 첫 실행 (표준: mktemp 사용, 검증 후 Trash로 이동)
|
|
30
44
|
FRESH="$(mktemp -d "${TMPDIR:-/tmp}/agentlas-smoke-XXXXXX")"
|