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
- if (arg === "--input" || arg === "-i") { flags.input = String(args[i + 1] ?? "").trim(); i += 1; continue; }
1303
- if (arg.startsWith("--input=")) { flags.input = arg.slice("--input=".length).trim(); continue; }
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
- mcpServers: [],
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": "10",
3
- "url": "https://github.com/agentlas-ai/agentlas-terminal/releases/download/desktop-core-v10/desktop-core.tar.gz",
4
- "sha256": "24276f065bdef65089f315b990f3573d88d5b47df650cb0deb023d979ecbcf95",
5
- "sizeBytes": 12556818,
6
- "writtenAt": "2026-08-19T21:31:43.680Z"
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.58",
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"