agentlas 1.0.58 → 1.0.60
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.
|
@@ -656,7 +656,7 @@ async function runGraph(ctx, needle, flags) {
|
|
|
656
656
|
// 시작 값이 필요한 그래프는 값 없이 요청하지 않는다. 값 없이 보내면 빈 채로 실행돼,
|
|
657
657
|
// 사용자가 요청한 적 없는 내용이 만들어진다.
|
|
658
658
|
const requirement = graphInputRequirement(graph, en);
|
|
659
|
-
if (requirement && !flags.input) {
|
|
659
|
+
if (requirement && !flags.inputProvided && !flags.input) {
|
|
660
660
|
ctx.err(en
|
|
661
661
|
? `"${row.name}" starts from a value you provide — ${requirement.label}.`
|
|
662
662
|
: `"${row.name}"은(는) 시작할 때 값을 받습니다 — ${requirement.label}.`);
|
|
@@ -676,7 +676,7 @@ async function runGraph(ctx, needle, flags) {
|
|
|
676
676
|
createdBy: row.created_by || "terminal",
|
|
677
677
|
graph,
|
|
678
678
|
};
|
|
679
|
-
const initialVars = requirement && flags.input ? { [requirement.varName]: flags.input } : {};
|
|
679
|
+
const initialVars = requirement && (flags.inputProvided || flags.input) ? { [requirement.varName]: flags.input } : {};
|
|
680
680
|
|
|
681
681
|
/*
|
|
682
682
|
* ★데몬 우선 (Phase 3). 데몬이 떠 있으면 이 터미널은 코어를 **로드하지 않는다** —
|
|
@@ -972,6 +972,37 @@ async function newGraph(ctx, request, flags) {
|
|
|
972
972
|
}
|
|
973
973
|
}
|
|
974
974
|
|
|
975
|
+
/*
|
|
976
|
+
* ★저장하기 **전에** 싼 단계를 실제로 돌려 본다.
|
|
977
|
+
* 빌더가 쓴 스크립트는 한 번도 돌아 본 적이 없다 — 실측 2026-08-20: 새로 만든 환율
|
|
978
|
+
* 자동화의 첫 단계가 자료원에서 403 을 받고 죽었고, 사람은 며칠 뒤 예약 실행에서야
|
|
979
|
+
* 알게 된다. code 단계 실행은 실측 0.0~0.1초라 사람이 못 느낀다.
|
|
980
|
+
* ★에러코드를 늘어놓지 않는다 — 고칠 수 있으면 조용히 고치고, 안 되면 사람 말로 한 줄.
|
|
981
|
+
*/
|
|
982
|
+
const core = await acquireCore(ctx);
|
|
983
|
+
const verifier = core && core.verifyBeforeSave;
|
|
984
|
+
if (verifier && typeof verifier.run === "function") {
|
|
985
|
+
try {
|
|
986
|
+
const seen = await verifier.run(built.graph);
|
|
987
|
+
for (const step of seen.steps || []) {
|
|
988
|
+
if (step.state === "repaired" && step.repairedCode) {
|
|
989
|
+
const node = built.graph.nodes.find((n) => n.id === step.nodeId);
|
|
990
|
+
if (node && node.config) node.config.code = step.repairedCode;
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
for (const line of verifier.render(seen)) ctx.out(ctx.ui.dim(line));
|
|
994
|
+
} catch (verifyError) {
|
|
995
|
+
/*
|
|
996
|
+
* ★확인하지 못한 것은 실패가 아니므로 저장은 막지 않는다. 다만 **조용히 삼키지도
|
|
997
|
+
* 않는다** — 실측 2026-08-20: 이 자리의 첫 판이 오타 하나로 매번 던졌는데,
|
|
998
|
+
* 빈 catch 가 그것을 통째로 먹어 "검증이 통과한 것"과 구분되지 않았다.
|
|
999
|
+
* 확인을 못 했으면 못 했다고 말한다.
|
|
1000
|
+
*/
|
|
1001
|
+
ctx.err(ctx.ui.dim(en
|
|
1002
|
+
? `Could not check the steps before saving: ${verifyError && verifyError.message}`
|
|
1003
|
+
: `저장 전 단계 확인을 하지 못했습니다: ${verifyError && verifyError.message}`));
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
975
1006
|
// 이름이 겹치면 덮어쓰지 않는다.
|
|
976
1007
|
const existing = graphRows(ctx, db).find((row) => row.name === bp.name);
|
|
977
1008
|
const name = existing ? `${bp.name} (2)` : bp.name;
|
|
@@ -1299,8 +1330,10 @@ async function run(ctx, args = []) {
|
|
|
1299
1330
|
const arg = args[i];
|
|
1300
1331
|
if (arg === "-y" || arg === "--yes") { flags.yes = true; continue; }
|
|
1301
1332
|
if (arg === "--start-over") { flags["start-over"] = true; continue; }
|
|
1302
|
-
|
|
1303
|
-
|
|
1333
|
+
// ★"안 줬다"와 "빈 값을 줬다"는 다르다. 그래프가 "비워 두면 최신 값을 씁니다"라고
|
|
1334
|
+
// 안내해도, 빈 문자열을 못 줘서 그 선택지를 고를 수 없었다(실측 2026-08-20).
|
|
1335
|
+
if (arg === "--input" || arg === "-i") { flags.input = String(args[i + 1] ?? "").trim(); flags.inputProvided = true; i += 1; continue; }
|
|
1336
|
+
if (arg.startsWith("--input=")) { flags.input = arg.slice("--input=".length).trim(); flags.inputProvided = true; continue; }
|
|
1304
1337
|
// ★--name 도 값을 하나 받는 플래그다. 걷어내지 않으면 그 값이 파일 경로에 붙어
|
|
1305
1338
|
// "그런 파일 없음"으로 죽는다 — `graph help`가 문법으로 광고하는 옵션인데
|
|
1306
1339
|
// 실제로는 한 번도 동작한 적이 없었다(실사용 실측 2026-08-06).
|
|
@@ -231,6 +231,18 @@ function loadDesktopCore(options = {}) {
|
|
|
231
231
|
initStore: req("store/db").initStore,
|
|
232
232
|
getDb: req("store/db").getDb,
|
|
233
233
|
runGraph: kernel.runGraph,
|
|
234
|
+
/*
|
|
235
|
+
* 저장 전 확인 — 빌더가 만든 스크립트를 **저장하기 전에** 돌려 보고, 안 되면 한 번
|
|
236
|
+
* 고친다. 옛 코어에는 없으므로 정직하게 null 로 둔다(부르는 쪽이 없으면 건너뛴다).
|
|
237
|
+
*/
|
|
238
|
+
verifyBeforeSave: (() => {
|
|
239
|
+
try {
|
|
240
|
+
const mod = req("workflow/verify-before-save");
|
|
241
|
+
return typeof mod.verifyGraphBeforeSaveWithKernel === "function"
|
|
242
|
+
? { run: mod.verifyGraphBeforeSaveWithKernel, render: mod.renderPreSaveVerification }
|
|
243
|
+
: null;
|
|
244
|
+
} catch { return null; }
|
|
245
|
+
})(),
|
|
234
246
|
getAutomation: req("store/automations").getAutomation,
|
|
235
247
|
// shared/ 는 electron/ 밖이라 req 로 못 닿는다 — 직접 해석한다.
|
|
236
248
|
graphExecutionDigest: (() => {
|
|
@@ -50,6 +50,23 @@ function quietSink() {
|
|
|
50
50
|
* @returns {Promise<{ok:true,text:string,runtime:string,fellBackFrom?:string}
|
|
51
51
|
* |{ok:false,reason:string,nextAction:string}>}
|
|
52
52
|
*/
|
|
53
|
+
/**
|
|
54
|
+
* 이 컴퓨터에서 **이미 동의된** MCP 서버들. 빌더도 실행기와 같은 재료를 본다.
|
|
55
|
+
*
|
|
56
|
+
* 새 동의를 받지 않는다 — 만드는 중에 승인 창을 띄우면 사람이 흐름에서 튕긴다.
|
|
57
|
+
* 못 읽으면 빈 배열: 예전 동작과 같아질 뿐 나빠지지 않는다(조용한 실패가 아니라
|
|
58
|
+
* "없는 것"이 사실이다).
|
|
59
|
+
*/
|
|
60
|
+
function consentedMcpServersFor(ctx) {
|
|
61
|
+
try {
|
|
62
|
+
const mcp = require("../mcp/index.cjs");
|
|
63
|
+
if (typeof mcp.readConsentedSystemMcpServers !== "function") return [];
|
|
64
|
+
return mcp.readConsentedSystemMcpServers(ctx.db(), { env: process.env }) || [];
|
|
65
|
+
} catch {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
53
70
|
async function askModel(ctx, prompt, opts = {}) {
|
|
54
71
|
const db = ctx.db();
|
|
55
72
|
let primary = null;
|
|
@@ -103,12 +120,27 @@ async function askModel(ctx, prompt, opts = {}) {
|
|
|
103
120
|
ui: quietSink(),
|
|
104
121
|
cwd: opts.cwd || process.cwd(),
|
|
105
122
|
prompt,
|
|
106
|
-
|
|
123
|
+
/*
|
|
124
|
+
* 읽기 권한 — 만드는 동안 바깥을 바꾸지 않는다. 메일이 나가거나 글이 올라가면 안 된다.
|
|
125
|
+
* ★런타임의 "read"는 **쓰기 금지가 아니라 도구 금지에 가깝다**(이 저장소 실측:
|
|
126
|
+
* 조회 그래프가 조회조차 못 했던 사고). 조회 도구는 남으므로 확인은 할 수 있다.
|
|
127
|
+
*/
|
|
107
128
|
permission: "read",
|
|
108
129
|
session: {},
|
|
109
130
|
model: runtime.model,
|
|
110
131
|
effort: runtime.effort,
|
|
111
|
-
|
|
132
|
+
/*
|
|
133
|
+
* ★사용자가 **이미 동의한** MCP 를 빌더에게도 준다.
|
|
134
|
+
*
|
|
135
|
+
* 실측 2026-08-20: 여기가 빈 배열이었다. 그래서 빌더는 이 컴퓨터에 무엇이
|
|
136
|
+
* 연결돼 있는지 모른 채 그래프를 지었고, 자기가 쓴 스크립트가 도는지도 볼 수
|
|
137
|
+
* 없었다. 도구는 제품에 다 있는데(브라우저·MCP·크리덴셜) **만드는 자리에만
|
|
138
|
+
* 안 닿아 있었다.**
|
|
139
|
+
*
|
|
140
|
+
* 새로 동의를 받지 않는다 — 이미 받아 둔 것만 그대로 쓴다(consent 영수증 기준).
|
|
141
|
+
* 못 읽으면 빈 배열로 간다: 예전과 같아질 뿐 나빠지지 않는다.
|
|
142
|
+
*/
|
|
143
|
+
mcpServers: consentedMcpServersFor(ctx),
|
|
112
144
|
mcpAllowlistMode: "exact",
|
|
113
145
|
});
|
|
114
146
|
} catch (err) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "
|
|
3
|
-
"url": "https://github.com/agentlas-ai/agentlas-terminal/releases/download/desktop-core-
|
|
4
|
-
"sha256": "
|
|
5
|
-
"sizeBytes":
|
|
6
|
-
"writtenAt": "2026-08-
|
|
2
|
+
"version": "12",
|
|
3
|
+
"url": "https://github.com/agentlas-ai/agentlas-terminal/releases/download/desktop-core-v12/desktop-core.tar.gz",
|
|
4
|
+
"sha256": "cc2ad07bd7695a9dcee4e61f7eb1f65ea86454caf79a6e449e5afb10d3ff8150",
|
|
5
|
+
"sizeBytes": 12563495,
|
|
6
|
+
"writtenAt": "2026-08-19T23:39:35.152Z"
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentlas",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.60",
|
|
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"
|