agentlas 1.0.57 → 1.0.59

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.
@@ -167,7 +167,28 @@ function listGraphs(ctx) {
167
167
  * 판단은 노드마다 둘 중 하나다 — "이미 일어났다(--done)" / "확실히 안 일어났다(--not-done)".
168
168
  * 아무 것도 주지 않으면 무엇을 정해야 하는지 보여 주기만 한다. 실행 중에 묻지 않는다.
169
169
  */
170
- function reconcileGraph(ctx, needle, flags, en) {
170
+ /**
171
+ * 엔진을 손에 넣는다 — 캐시에 없으면 **받는다**.
172
+ *
173
+ * ★엔진이 필요한 명령은 전부 이 길을 지나야 한다. 실측 2026-08-20: `graph run` 은 이걸
174
+ * 고쳤는데, 바로 뒤에 만든 `graph reconcile` 이 동기 로더만 불러 같은 병을 반복했다 —
175
+ * 새로 설치한 사람에게는 "이 엔진에는 재조정 기능이 없습니다" 로 보인다(사실은 엔진이
176
+ * 아직 없는 것이다). 한 곳으로 모아 다음 명령이 또 빠뜨리지 않게 한다.
177
+ */
178
+ async function acquireCore(ctx) {
179
+ const desktopCore = require("../core/desktop-core.cjs");
180
+ let core = ctx.desktopCore || desktopCore.loadDesktopCore();
181
+ if (!core || core.error || typeof core.runGraph !== "function") {
182
+ try {
183
+ core = await desktopCore.loadDesktopCoreAsync({ onNotice: (message) => ctx.err(message) });
184
+ } catch {
185
+ return null;
186
+ }
187
+ }
188
+ return core && !core.error ? core : null;
189
+ }
190
+
191
+ async function reconcileGraph(ctx, needle, flags, en) {
171
192
  const rows = graphRows(ctx, ctx.db());
172
193
  const row = findGraph(rows, needle);
173
194
  if (row?.ambiguous) { reportAmbiguous(ctx, needle, row.ambiguous, en); return 1; }
@@ -175,7 +196,7 @@ function reconcileGraph(ctx, needle, flags, en) {
175
196
  ctx.err(en ? `No graph matches "${needle}".` : `"${needle}"와 맞는 그래프가 없습니다.`);
176
197
  return 1;
177
198
  }
178
- const core = ctx.desktopCore || require("../core/desktop-core.cjs").loadDesktopCore();
199
+ const core = await acquireCore(ctx);
179
200
  const reconciliation = core && core.graphReconciliation;
180
201
  if (!reconciliation || typeof reconciliation.get !== "function") {
181
202
  ctx.err(en
@@ -183,6 +204,35 @@ function reconcileGraph(ctx, needle, flags, en) {
183
204
  : "이 엔진에는 재조정 기능이 없습니다. CLI를 업데이트한 뒤(`npm i -g agentlas@latest`) 다시 시도하세요.");
184
205
  return 1;
185
206
  }
207
+ // 그래프를 고친 뒤에는 옛 좌표가 그 그래프의 것이 아니라 재조정도 거절된다. 그 상태는
208
+ // 실행도 재조정도 안 되는 잠김이므로, 사람이 스스로 나갈 문을 둔다.
209
+ if (flags && flags['start-over']) {
210
+ if (typeof reconciliation.forgetStale !== 'function') {
211
+ ctx.err(en ? 'This engine build cannot do that. Update the CLI and try again.' : '이 엔진에는 그 기능이 없습니다. CLI를 업데이트한 뒤 다시 시도하세요.');
212
+ return 1;
213
+ }
214
+ const graph = parseGraph(row);
215
+ const automation = core.getAutomation ? core.getAutomation(row.id) : null;
216
+ const digest = core.graphExecutionDigest && automation && graph
217
+ ? core.graphExecutionDigest(automation, graph)
218
+ : null;
219
+ if (!digest) {
220
+ ctx.err(en ? 'Could not compute the current graph identity.' : '지금 그래프의 신원을 계산하지 못했습니다.');
221
+ return 1;
222
+ }
223
+ const outcome = reconciliation.forgetStale(row.id, digest);
224
+ if (!outcome.forgot) {
225
+ ctx.err(en
226
+ ? `Nothing to forget (${outcome.reason}). If the graph has not changed, decide each step instead.`
227
+ : `잊을 것이 없습니다(${outcome.reason}). 그래프가 그대로라면, 단계마다 정하는 쪽이 맞습니다.`);
228
+ return 1;
229
+ }
230
+ ctx.out(en
231
+ ? 'The earlier run is forgotten. Note: whatever it already did can happen again on the next run.'
232
+ : '이전 실행을 잊었습니다. 그 실행이 이미 한 일은 다음 실행에서 다시 일어날 수 있습니다.');
233
+ return 0;
234
+ }
235
+
186
236
  const view = reconciliation.get(row.id);
187
237
  if (!view) {
188
238
  ctx.out(en
@@ -606,7 +656,7 @@ async function runGraph(ctx, needle, flags) {
606
656
  // 시작 값이 필요한 그래프는 값 없이 요청하지 않는다. 값 없이 보내면 빈 채로 실행돼,
607
657
  // 사용자가 요청한 적 없는 내용이 만들어진다.
608
658
  const requirement = graphInputRequirement(graph, en);
609
- if (requirement && !flags.input) {
659
+ if (requirement && !flags.inputProvided && !flags.input) {
610
660
  ctx.err(en
611
661
  ? `"${row.name}" starts from a value you provide — ${requirement.label}.`
612
662
  : `"${row.name}"은(는) 시작할 때 값을 받습니다 — ${requirement.label}.`);
@@ -626,7 +676,7 @@ async function runGraph(ctx, needle, flags) {
626
676
  createdBy: row.created_by || "terminal",
627
677
  graph,
628
678
  };
629
- const initialVars = requirement && flags.input ? { [requirement.varName]: flags.input } : {};
679
+ const initialVars = requirement && (flags.inputProvided || flags.input) ? { [requirement.varName]: flags.input } : {};
630
680
 
631
681
  /*
632
682
  * ★데몬 우선 (Phase 3). 데몬이 떠 있으면 이 터미널은 코어를 **로드하지 않는다** —
@@ -668,19 +718,10 @@ async function runGraph(ctx, needle, flags) {
668
718
  *
669
719
  * 받는 동안은 조용하지 않다(onNotice) — 12MB 를 말없이 끌어오지 않는다.
670
720
  */
671
- let core = ctx.desktopCore || desktopCore.loadDesktopCore();
672
- if (!core || core.error || typeof core.runGraph !== "function") {
673
- try {
674
- core = await desktopCore.loadDesktopCoreAsync({ onNotice: (message) => ctx.err(message) });
675
- } catch (fetchError) {
676
- ctx.err(JSON.stringify({
677
- ok: false,
678
- error: `graph-execution engine could not be fetched: ${fetchError instanceof Error ? fetchError.message : String(fetchError)}`,
679
- }, null, 2));
680
- return 1;
681
- }
682
- }
683
- if (!core || core.error || typeof core.runGraph !== "function") {
721
+ // ★엔진을 얻는 법을 아는 곳은 acquireCore 하나뿐이다 — 둘이면 다음에 만드는 명령이
722
+ // 또 한쪽만 보고 캐시에서 끝난다(실측 2026-08-20: reconcile 정확히 그랬다).
723
+ let core = await acquireCore(ctx);
724
+ if (!core || typeof core.runGraph !== "function") {
684
725
  const cause = core?.error instanceof Error ? core.error.message : "vendored Desktop Core is unavailable";
685
726
  ctx.err(JSON.stringify({ ok: false, error: cause }, null, 2));
686
727
  return 1;
@@ -1257,8 +1298,11 @@ async function run(ctx, args = []) {
1257
1298
  for (let i = 0; i < args.length; i += 1) {
1258
1299
  const arg = args[i];
1259
1300
  if (arg === "-y" || arg === "--yes") { flags.yes = true; continue; }
1260
- if (arg === "--input" || arg === "-i") { flags.input = String(args[i + 1] ?? "").trim(); i += 1; continue; }
1261
- if (arg.startsWith("--input=")) { flags.input = arg.slice("--input=".length).trim(); continue; }
1301
+ if (arg === "--start-over") { flags["start-over"] = true; continue; }
1302
+ // "안 줬다" "빈 값을 줬다"는 다르다. 그래프가 "비워 두면 최신 값을 씁니다"라고
1303
+ // 안내해도, 빈 문자열을 못 줘서 그 선택지를 고를 수 없었다(실측 2026-08-20).
1304
+ if (arg === "--input" || arg === "-i") { flags.input = String(args[i + 1] ?? "").trim(); flags.inputProvided = true; i += 1; continue; }
1305
+ if (arg.startsWith("--input=")) { flags.input = arg.slice("--input=".length).trim(); flags.inputProvided = true; continue; }
1262
1306
  // ★--name 도 값을 하나 받는 플래그다. 걷어내지 않으면 그 값이 파일 경로에 붙어
1263
1307
  // "그런 파일 없음"으로 죽는다 — `graph help`가 문법으로 광고하는 옵션인데
1264
1308
  // 실제로는 한 번도 동작한 적이 없었다(실사용 실측 2026-08-06).
@@ -1320,7 +1364,7 @@ async function run(ctx, args = []) {
1320
1364
  : "사용법: agentlas graph reconcile \"<이름>\" [--done <노드>] [--not-done <노드>] [--output <노드>=<값>]");
1321
1365
  return 1;
1322
1366
  }
1323
- return reconcileGraph(ctx, target, flags, en);
1367
+ return await reconcileGraph(ctx, target, flags, en);
1324
1368
  }
1325
1369
  if (sub === "export") {
1326
1370
  if (!target) {
@@ -231,6 +231,12 @@ function loadDesktopCore(options = {}) {
231
231
  initStore: req("store/db").initStore,
232
232
  getDb: req("store/db").getDb,
233
233
  runGraph: kernel.runGraph,
234
+ getAutomation: req("store/automations").getAutomation,
235
+ // shared/ 는 electron/ 밖이라 req 로 못 닿는다 — 직접 해석한다.
236
+ graphExecutionDigest: (() => {
237
+ try { return require(path.join(root, "shared", "graph-execution-digest.js")).graphExecutionDigest; }
238
+ catch { return null; }
239
+ })(),
234
240
  graphFailureOf: kernel.graphFailureOf,
235
241
  planGraphLoops: kernel.planGraphLoops,
236
242
  /*
@@ -246,6 +252,7 @@ function loadDesktopCore(options = {}) {
246
252
  return {
247
253
  get: mod.getAutomationGraphReconciliation,
248
254
  apply: mod.reconcileAutomationGraph,
255
+ forgetStale: mod.forgetStaleGraphCheckpoint,
249
256
  };
250
257
  } catch {
251
258
  return null;
@@ -1,7 +1,7 @@
1
1
  {
2
- "version": "9",
3
- "url": "https://github.com/agentlas-ai/agentlas-terminal/releases/download/desktop-core-v9/desktop-core.tar.gz",
4
- "sha256": "1660ff39c1d06840f5b5f047e2520df32b20b2efb70cf1e5cd4f5e43814837a2",
5
- "sizeBytes": 12553853,
6
- "writtenAt": "2026-08-19T20:57:26.499Z"
2
+ "version": "11",
3
+ "url": "https://github.com/agentlas-ai/agentlas-terminal/releases/download/desktop-core-v11/desktop-core.tar.gz",
4
+ "sha256": "c68cddd2cd4ee6978903a7a1bea39fbdce218c1dcbaa74165231ea99bbd1999e",
5
+ "sizeBytes": 12557470,
6
+ "writtenAt": "2026-08-19T22:35:51.167Z"
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentlas",
3
- "version": "1.0.57",
3
+ "version": "1.0.59",
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"