agentlas 1.0.46 → 1.0.48
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 +33 -0
- package/README.md +7 -7
- package/engine/acp/server.cjs +279 -0
- package/engine/agentlas-capabilities.cjs +4 -2
- package/engine/agentlas-core-harness.cjs +18 -0
- package/engine/agentlas-i18n.cjs +8 -8
- package/engine/agentlas-input.cjs +3 -2
- package/engine/agentlas-native-host.cjs +130 -11
- package/engine/agentlas-onboard.cjs +9 -3
- package/engine/agentlas-permissions.cjs +5 -1
- package/engine/agentlas-workforce.cjs +81 -24
- package/engine/agents/router.cjs +4 -2
- package/engine/architecture.data.json +6 -30
- package/engine/automation/daemon.cjs +3 -7
- package/engine/bootstrap-schema.sql +216 -191
- package/engine/browser/cdp.cjs +10 -4
- package/engine/cloud-assets/commands.cjs +1 -1
- package/engine/cloud-assets/package.cjs +161 -45
- package/engine/commands/acp.cjs +45 -0
- package/engine/commands/billing.cjs +2 -2
- package/engine/commands/call.cjs +4 -0
- package/engine/commands/context.cjs +14 -3
- package/engine/commands/doctor.cjs +8 -4
- package/engine/commands/graph.cjs +46 -54
- package/engine/commands/index.cjs +2 -0
- package/engine/commands/search.cjs +2 -2
- package/engine/commands/workforce.cjs +11 -0
- package/engine/core/desktop-core.cjs +93 -1
- package/engine/firms/orchestrate.cjs +32 -1
- package/engine/graph/interview.cjs +2 -11
- package/engine/graph/vocabulary.generated.cjs +1 -1
- package/engine/hephaestus/runtime.cjs +2 -6
- package/engine/project/memory-context.cjs +20 -7
- package/engine/project/seed.cjs +46 -31
- package/engine/project/state.cjs +8 -1
- package/engine/runtimes/acp-driver.cjs +96 -0
- package/engine/runtimes/auth-evidence.cjs +6 -0
- package/engine/runtimes/detect.cjs +3 -13
- package/engine/runtimes/kinds.cjs +84 -0
- package/engine/runtimes/resolve.cjs +67 -14
- package/engine/sessions/prompt.cjs +2 -2
- package/engine/ui/commands-catalog.cjs +2 -0
- package/engine/ui/palette.cjs +2 -1
- package/engine/ui/repl.cjs +4 -3
- package/engine/ui/shell.cjs +43 -5
- package/engine/vendor/desktop-core.manifest.json +5 -5
- package/engine/workforce/capture.cjs +55 -10
- package/engine/workforce/deps.cjs +2 -2
- package/engine/workforce/local-core-transport.cjs +13 -19
- package/package.json +2 -1
- package/engine/project/super-ontology-seed.json +0 -3288
|
@@ -24,13 +24,10 @@ const path = require("node:path");
|
|
|
24
24
|
const { spawn } = require("node:child_process");
|
|
25
25
|
const { dbPath, userDataDir } = require("../core/paths.cjs");
|
|
26
26
|
|
|
27
|
-
// 캡처 드라이버가 검증된 런타임만.
|
|
28
|
-
// 있지만 buildArgs/텍스트 추출 계약이 없으므로
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
codex: "codex",
|
|
32
|
-
gemini: "gemini",
|
|
33
|
-
};
|
|
27
|
+
// 캡처 드라이버가 검증된 런타임만. 정본(runtimes/kinds.cjs)의 RUNTIME_BIN에는 kimi/grok/cursor도
|
|
28
|
+
// 있지만 buildArgs/텍스트 추출 계약이 없으므로 캡처 검증 파생본만 쓴다 — 새 kind 를
|
|
29
|
+
// 정본에 추가해도 capture:true 를 명시하기 전엔 여기 조용히 들어오지 않는다.
|
|
30
|
+
const { CAPTURE_RUNTIME_BIN: RUNTIME_BIN } = require("../runtimes/kinds.cjs");
|
|
34
31
|
|
|
35
32
|
const SERVICE = "com.agentlas.desktop";
|
|
36
33
|
|
|
@@ -198,6 +195,14 @@ function buildArgs(kind, systemPrompt, prompt, permission, runtimeOptions = {})
|
|
|
198
195
|
const mcp = native.geminiMcpIsolationArgs();
|
|
199
196
|
return ["--prompt", `[SYSTEM]\n${systemPrompt}\n\n${prompt}`, ...(model ? ["-m", model] : []), ...perm, ...noAuthorityArgs, ...mcp];
|
|
200
197
|
}
|
|
198
|
+
if (kind === "agy") {
|
|
199
|
+
return native.agyArgs({
|
|
200
|
+
prompt,
|
|
201
|
+
systemPrompt,
|
|
202
|
+
permission: noAuthority ? "read" : level,
|
|
203
|
+
model,
|
|
204
|
+
});
|
|
205
|
+
}
|
|
201
206
|
return [prompt];
|
|
202
207
|
}
|
|
203
208
|
|
|
@@ -287,6 +292,7 @@ function capturedRuntimeUsage(kind, raw) {
|
|
|
287
292
|
}
|
|
288
293
|
const direct =
|
|
289
294
|
genericUsage(event?.usage) ||
|
|
295
|
+
genericUsage(event?.step_update?.usage) ||
|
|
290
296
|
genericUsage(event?.usageMetadata) ||
|
|
291
297
|
genericUsage(event?.stats);
|
|
292
298
|
if (direct) return direct;
|
|
@@ -346,6 +352,12 @@ function capturedRuntimeFailure(kind, raw, text) {
|
|
|
346
352
|
return { message: `gemini ${event.status}`, source: "marker" };
|
|
347
353
|
}
|
|
348
354
|
}
|
|
355
|
+
if (kind === "agy" && event.event === "result") {
|
|
356
|
+
const status = String(event.result?.status || "").toLowerCase();
|
|
357
|
+
if (status && !["success", "completed", "done"].includes(status)) {
|
|
358
|
+
return { message: `agy ${status}`, source: "marker" };
|
|
359
|
+
}
|
|
360
|
+
}
|
|
349
361
|
}
|
|
350
362
|
// 표식이 전혀 없는 케이스(codex 한도) — 휴리스틱 최후 그물, 출처 표기.
|
|
351
363
|
const refusal = detectRuntimeRefusal(text);
|
|
@@ -399,6 +411,21 @@ function capturedRuntimeAgentText(kind, raw) {
|
|
|
399
411
|
return final ? String(final.result ?? final.response) : "";
|
|
400
412
|
}
|
|
401
413
|
|
|
414
|
+
if (kind === "agy") {
|
|
415
|
+
const isProtocol = events.some((event) =>
|
|
416
|
+
event?.event === "step_update" || event?.event === "result",
|
|
417
|
+
);
|
|
418
|
+
if (!isProtocol) return text.trim();
|
|
419
|
+
const final = [...events].reverse().find((event) =>
|
|
420
|
+
event?.event === "result" && typeof event.result?.response === "string",
|
|
421
|
+
);
|
|
422
|
+
if (final) return final.result.response;
|
|
423
|
+
return events
|
|
424
|
+
.filter((event) => event?.event === "step_update" && event.step_update?.step_type === "agent_response")
|
|
425
|
+
.map((event) => typeof event.step_update?.text_delta === "string" ? event.step_update.text_delta : "")
|
|
426
|
+
.join("");
|
|
427
|
+
}
|
|
428
|
+
|
|
402
429
|
return text.trim();
|
|
403
430
|
}
|
|
404
431
|
|
|
@@ -423,6 +450,7 @@ function captureRuntime(kind, systemPrompt, prompt, opts) {
|
|
|
423
450
|
// 계약 테스트용 실행 파일 주입(가짜 CLI가 픽스처를 cat) — 프로덕션 경로에선 없음.
|
|
424
451
|
const bin = opts.binOverride || which(RUNTIME_BIN[kind]) || RUNTIME_BIN[kind];
|
|
425
452
|
let child;
|
|
453
|
+
let launchCleanup = () => {};
|
|
426
454
|
try {
|
|
427
455
|
const spawnImpl = opts.spawn || spawn;
|
|
428
456
|
const env = nativeHost.runtimeEnvForKind(kind, opts.env || process.env, {
|
|
@@ -431,13 +459,28 @@ function captureRuntime(kind, systemPrompt, prompt, opts) {
|
|
|
431
459
|
mcpAllowlistMode: kind === "gemini" ? "exact" : undefined,
|
|
432
460
|
});
|
|
433
461
|
const groupedChild = process.platform !== "win32" && spawnImpl === spawn;
|
|
434
|
-
|
|
462
|
+
const runtimeOptions = {
|
|
435
463
|
model: opts.model,
|
|
436
464
|
effort: opts.effort,
|
|
437
465
|
authorityMode: opts.authorityMode,
|
|
438
466
|
noToolsPolicyPath: opts.noToolsPolicyPath,
|
|
439
467
|
allowedNativeTools: opts.allowedNativeTools,
|
|
440
|
-
}
|
|
468
|
+
};
|
|
469
|
+
let childArgs = buildArgs(kind, systemPrompt, prompt, opts.permission, runtimeOptions);
|
|
470
|
+
if (kind === "agy") {
|
|
471
|
+
const prepared = nativeHost.prepareAgyLaunch({
|
|
472
|
+
prompt,
|
|
473
|
+
systemPrompt,
|
|
474
|
+
permission: opts.authorityMode === "no-authority" ? "read" : opts.permission,
|
|
475
|
+
model: opts.model,
|
|
476
|
+
}, {
|
|
477
|
+
platform: opts.platform,
|
|
478
|
+
promptLimit: opts.agyPromptLimit,
|
|
479
|
+
});
|
|
480
|
+
childArgs = prepared.args;
|
|
481
|
+
launchCleanup = prepared.cleanup;
|
|
482
|
+
}
|
|
483
|
+
child = spawnImpl(bin, childArgs, {
|
|
441
484
|
cwd,
|
|
442
485
|
stdio: ["ignore", "pipe", "pipe"],
|
|
443
486
|
env,
|
|
@@ -446,6 +489,7 @@ function captureRuntime(kind, systemPrompt, prompt, opts) {
|
|
|
446
489
|
});
|
|
447
490
|
child.__agentlasGroupedChild = groupedChild;
|
|
448
491
|
} catch (error) {
|
|
492
|
+
launchCleanup();
|
|
449
493
|
reject(error);
|
|
450
494
|
return;
|
|
451
495
|
}
|
|
@@ -479,6 +523,7 @@ function captureRuntime(kind, systemPrompt, prompt, opts) {
|
|
|
479
523
|
child.removeListener("error", onError);
|
|
480
524
|
child.removeListener("close", onClose);
|
|
481
525
|
if (opts.signal) opts.signal.removeEventListener?.("abort", onAbort);
|
|
526
|
+
launchCleanup();
|
|
482
527
|
};
|
|
483
528
|
const finishReject = (error) => {
|
|
484
529
|
if (settled) return;
|
|
@@ -562,7 +607,7 @@ function captureRuntime(kind, systemPrompt, prompt, opts) {
|
|
|
562
607
|
let text;
|
|
563
608
|
if (kind === "codex" && opts.authorityMode === "no-authority") {
|
|
564
609
|
text = codexCaptureAgentText(raw);
|
|
565
|
-
} else if (kind === "claude-code" || kind === "gemini") {
|
|
610
|
+
} else if (kind === "claude-code" || kind === "gemini" || kind === "agy") {
|
|
566
611
|
text = capturedRuntimeAgentText(kind, raw);
|
|
567
612
|
} else {
|
|
568
613
|
text = raw;
|
|
@@ -109,7 +109,7 @@ function legacyWorkforceRuntime(db, override) {
|
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
const error = new Error(
|
|
112
|
-
"no_runtime: no agent CLI or connected API runtime found (claude / codex / gemini / BYOK / Ollama).",
|
|
112
|
+
"no_runtime: no agent CLI or connected API runtime found (claude / codex / Antigravity agy / legacy gemini / BYOK / Ollama).",
|
|
113
113
|
);
|
|
114
114
|
error.code = "no_runtime";
|
|
115
115
|
throw error;
|
|
@@ -513,7 +513,7 @@ function projectContextSlice(projectPath, task) {
|
|
|
513
513
|
if (!projectPath || !String(task || "").trim()) return "";
|
|
514
514
|
try {
|
|
515
515
|
const core = coreHarness();
|
|
516
|
-
const coreRoot = core.
|
|
516
|
+
const coreRoot = core.resolveContextMapCoreRoot();
|
|
517
517
|
if (!coreRoot) return "";
|
|
518
518
|
const result = core.captureCoreJsonSync(
|
|
519
519
|
"agentlas_cloud",
|
|
@@ -7,16 +7,14 @@
|
|
|
7
7
|
* search_candidates 요청 {workOrder, sourceScope}
|
|
8
8
|
* 응답 agentlas.workforce-federation-result.v1 봉투
|
|
9
9
|
* → 루프에는 봉투를 벗긴 candidateSet만 준다.
|
|
10
|
-
* validate_selection 요청 {workOrder, selection
|
|
11
|
-
* (
|
|
12
|
-
* Core는 자기 선택 세션에서 연합을 이미 안다)
|
|
10
|
+
* validate_selection 요청 {workOrder, selection}
|
|
11
|
+
* (Core는 selectionSessionId로 자기 핀 세션을 복원한다)
|
|
13
12
|
* 응답 안의 selectionValidation이 정확히
|
|
14
13
|
* agentlas.workforce-selection-validation.v1 — 루프 검증기와
|
|
15
14
|
* 동일 계약이라 그대로 돌려준다. 원본 응답은 여기 상태로
|
|
16
15
|
* 붙잡아 둔다(prepare가 요구).
|
|
17
|
-
* prepare_execution 요청 {workOrder, selection,
|
|
18
|
-
* federatedSelection: <validate 원본 응답>,
|
|
19
|
-
* validationReceipt: <동일>, projectDir}
|
|
16
|
+
* prepare_execution 요청 {workOrder, selection,
|
|
17
|
+
* federatedSelection: <validate 원본 응답>, projectDir}
|
|
20
18
|
* 응답 안의 executionPlan이 정확히
|
|
21
19
|
* agentlas.workforce-execution-plan.v5 (roster에
|
|
22
20
|
* directiveBundle·permissionPolicy 동봉) — 그대로 돌려준다.
|
|
@@ -115,7 +113,7 @@ function createLocalCoreHubTool({ sourceScope, projectDir, cwd, client } = {}) {
|
|
|
115
113
|
const core = client || createLocalCoreClient({ cwd: cwd || projectDir });
|
|
116
114
|
// 편성 계보 상태 — 전부 "Core 어휘"(opaque id) 원본이다:
|
|
117
115
|
// maps: 마지막 search 의 id 지도. 재검색(refinement)마다 재구성된다.
|
|
118
|
-
// coreCandidateSet: Core 가 준
|
|
116
|
+
// coreCandidateSet: Core 가 준 요약 메뉴. 로컬 계보 확인에만 쓰며 반송하지 않는다.
|
|
119
117
|
// lastValidationEnvelope: validate 원본 응답. prepare 의 federatedSelection 은
|
|
120
118
|
// 이것이어야 한다 — 루프가 들고 있는 것은 벗겨낸 selectionValidation 뿐이다.
|
|
121
119
|
let maps = { forward: new Map(), reverse: new Map() };
|
|
@@ -137,12 +135,11 @@ function createLocalCoreHubTool({ sourceScope, projectDir, cwd, client } = {}) {
|
|
|
137
135
|
maps = buildIdMaps(args.workOrder);
|
|
138
136
|
coreCandidateSet = null;
|
|
139
137
|
lastValidationEnvelope = null;
|
|
140
|
-
//
|
|
141
|
-
//
|
|
142
|
-
// reference-first 메뉴는 candidate_set_invalid 로 거절된다).
|
|
138
|
+
// Current Core keeps the full dossier in its pinned session and returns a
|
|
139
|
+
// numbered decision menu. Do not request the legacy full-echo form.
|
|
143
140
|
let envelope;
|
|
144
141
|
try {
|
|
145
|
-
envelope = await core.call(name, { workOrder: mapDeep(args.workOrder, maps.forward), sourceScope
|
|
142
|
+
envelope = await core.call(name, { workOrder: mapDeep(args.workOrder, maps.forward), sourceScope });
|
|
146
143
|
} catch (error) {
|
|
147
144
|
// 반응형 정규화(1회): 경계가 지목한 finite 값만 opaque 로 바꿔 재시도.
|
|
148
145
|
const issues = error.code === "work_order_hub_boundary_rejected" ? boundaryIssues(error) : null;
|
|
@@ -161,7 +158,7 @@ function createLocalCoreHubTool({ sourceScope, projectDir, cwd, client } = {}) {
|
|
|
161
158
|
repaired += 1;
|
|
162
159
|
}
|
|
163
160
|
if (!repaired) throw error;
|
|
164
|
-
envelope = await core.call(name, { workOrder: mapDeep(args.workOrder, maps.forward), sourceScope
|
|
161
|
+
envelope = await core.call(name, { workOrder: mapDeep(args.workOrder, maps.forward), sourceScope });
|
|
165
162
|
}
|
|
166
163
|
const candidateSet = envelope && envelope.candidateSet;
|
|
167
164
|
if (!candidateSet || typeof candidateSet !== "object") throw invalid("local Core federation returned no candidateSet");
|
|
@@ -174,9 +171,10 @@ function createLocalCoreHubTool({ sourceScope, projectDir, cwd, client } = {}) {
|
|
|
174
171
|
error.code = "local_core_lineage_missing";
|
|
175
172
|
throw error;
|
|
176
173
|
}
|
|
177
|
-
//
|
|
178
|
-
|
|
179
|
-
|
|
174
|
+
// The host-authored selection must point at the exact summary menu just
|
|
175
|
+
// returned. Core independently reloads and verifies the full pinned set.
|
|
176
|
+
if (args.selection?.candidateSetDigest !== coreCandidateSet.candidateSetDigest) {
|
|
177
|
+
throw invalid("selection lineage mismatch between the loop and the local Core session");
|
|
180
178
|
}
|
|
181
179
|
let envelope;
|
|
182
180
|
let coreSelection = mapDeep(args.selection, maps.forward);
|
|
@@ -184,7 +182,6 @@ function createLocalCoreHubTool({ sourceScope, projectDir, cwd, client } = {}) {
|
|
|
184
182
|
envelope = await core.call(name, {
|
|
185
183
|
workOrder: mapDeep(args.workOrder, maps.forward),
|
|
186
184
|
selection: coreSelection,
|
|
187
|
-
candidateSet: coreCandidateSet,
|
|
188
185
|
});
|
|
189
186
|
} catch (error) {
|
|
190
187
|
/*
|
|
@@ -205,7 +202,6 @@ function createLocalCoreHubTool({ sourceScope, projectDir, cwd, client } = {}) {
|
|
|
205
202
|
envelope = await core.call(name, {
|
|
206
203
|
workOrder: mapDeep(args.workOrder, maps.forward),
|
|
207
204
|
selection: repairedSelection,
|
|
208
|
-
candidateSet: coreCandidateSet,
|
|
209
205
|
});
|
|
210
206
|
coreSelection = repairedSelection;
|
|
211
207
|
}
|
|
@@ -224,9 +220,7 @@ function createLocalCoreHubTool({ sourceScope, projectDir, cwd, client } = {}) {
|
|
|
224
220
|
workOrder: mapDeep(args.workOrder, maps.forward),
|
|
225
221
|
// validate 가 수락한 정확한 본 — 반응형 reasonCode 수리를 반영한다.
|
|
226
222
|
selection: lastCoreSelection || mapDeep(args.selection, maps.forward),
|
|
227
|
-
candidateSet: coreCandidateSet,
|
|
228
223
|
federatedSelection: lastValidationEnvelope,
|
|
229
|
-
validationReceipt: lastValidationEnvelope,
|
|
230
224
|
projectDir,
|
|
231
225
|
});
|
|
232
226
|
if (!envelope || typeof envelope.executionPlan !== "object") throw invalid("local Core preparation returned no executionPlan");
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentlas",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.48",
|
|
4
4
|
"description": "Agentlas project terminal — run project controllers and task-scoped agent teams from the terminal. Standalone: no desktop app process required.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"agentlas": "bin/agentlas.cjs"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
|
+
"test": "sh test/smoke.sh",
|
|
9
10
|
"smoke": "sh test/smoke.sh",
|
|
10
11
|
"test:release-contracts": "npm run smoke",
|
|
11
12
|
"sync:architecture": "node scripts/sync-architecture-from-desktop.cjs",
|