agentlas 0.9.10 → 1.0.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.
Files changed (145) hide show
  1. package/CHANGELOG.md +106 -0
  2. package/README.md +319 -341
  3. package/bin/agentlas.cjs +32 -9
  4. package/engine/agentlas-banner.cjs +24 -3
  5. package/engine/agentlas-composer.cjs +239 -31
  6. package/engine/agentlas-config.cjs +103 -7
  7. package/engine/agentlas-core-harness.cjs +48 -4
  8. package/engine/agentlas-evolution.cjs +3 -4
  9. package/engine/agentlas-i18n.cjs +88 -32
  10. package/engine/agentlas-input.cjs +234 -18
  11. package/engine/agentlas-memory-governance.cjs +3 -5
  12. package/engine/agentlas-memory-import.cjs +3 -3
  13. package/engine/agentlas-native-host.cjs +200 -9
  14. package/engine/agentlas-onboard.cjs +112 -20
  15. package/engine/agentlas-permissions.cjs +14 -7
  16. package/engine/agentlas-sqlite-policy.cjs +34 -0
  17. package/engine/agentlas-ui.cjs +93 -42
  18. package/engine/agentlas-workforce.cjs +472 -58
  19. package/engine/agentlas-workload-routing.cjs +8 -3
  20. package/engine/agentlas.cjs +140 -12367
  21. package/engine/agents/files.cjs +61 -0
  22. package/engine/agents/import-local.cjs +237 -0
  23. package/engine/agents/registry.cjs +158 -0
  24. package/engine/agents/router.cjs +565 -0
  25. package/engine/agents/routes.cjs +43 -0
  26. package/engine/architecture.data.json +2 -2
  27. package/engine/automation/daemon.cjs +335 -0
  28. package/engine/automation/schedule.cjs +181 -0
  29. package/engine/automation/store.cjs +209 -0
  30. package/engine/cloud/auth.cjs +279 -0
  31. package/engine/cloud/hub-client.cjs +239 -0
  32. package/engine/cloud-assets/cargo.cjs +49 -0
  33. package/engine/cloud-assets/cas.cjs +235 -0
  34. package/engine/cloud-assets/commands.cjs +273 -0
  35. package/engine/cloud-assets/package.cjs +936 -0
  36. package/engine/cloud-assets/restore.cjs +172 -0
  37. package/engine/cloud-assets/state.cjs +268 -0
  38. package/engine/commands/automation.cjs +195 -0
  39. package/engine/commands/billing.cjs +96 -0
  40. package/engine/commands/browser.cjs +20 -0
  41. package/engine/commands/build.cjs +33 -0
  42. package/engine/commands/call.cjs +24 -0
  43. package/engine/commands/career-graph.cjs +51 -0
  44. package/engine/commands/cd.cjs +22 -0
  45. package/engine/commands/chat.cjs +12 -0
  46. package/engine/commands/chats.cjs +28 -0
  47. package/engine/commands/cloud.cjs +17 -0
  48. package/engine/commands/connect.cjs +20 -0
  49. package/engine/commands/context.cjs +66 -0
  50. package/engine/commands/creds.cjs +203 -0
  51. package/engine/commands/doctor.cjs +68 -0
  52. package/engine/commands/env.cjs +33 -0
  53. package/engine/commands/evolve.cjs +23 -0
  54. package/engine/commands/experience.cjs +34 -0
  55. package/engine/commands/film.cjs +8 -0
  56. package/engine/commands/firm.cjs +115 -0
  57. package/engine/commands/help.cjs +65 -0
  58. package/engine/commands/hep.cjs +23 -0
  59. package/engine/commands/import.cjs +35 -0
  60. package/engine/commands/index.cjs +136 -0
  61. package/engine/commands/install.cjs +27 -0
  62. package/engine/commands/journal.cjs +31 -0
  63. package/engine/commands/legacy-network.cjs +29 -0
  64. package/engine/commands/list.cjs +49 -0
  65. package/engine/commands/login.cjs +68 -0
  66. package/engine/commands/logout.cjs +28 -0
  67. package/engine/commands/mcp.cjs +91 -0
  68. package/engine/commands/memory.cjs +21 -0
  69. package/engine/commands/multimodal.cjs +91 -0
  70. package/engine/commands/native.cjs +34 -0
  71. package/engine/commands/netadmin.cjs +31 -0
  72. package/engine/commands/oberon.cjs +70 -0
  73. package/engine/commands/ontology.cjs +24 -0
  74. package/engine/commands/open.cjs +48 -0
  75. package/engine/commands/plugin.cjs +101 -0
  76. package/engine/commands/project.cjs +47 -0
  77. package/engine/commands/research.cjs +36 -0
  78. package/engine/commands/route.cjs +37 -0
  79. package/engine/commands/run.cjs +149 -0
  80. package/engine/commands/search.cjs +55 -0
  81. package/engine/commands/setup.cjs +45 -0
  82. package/engine/commands/storm.cjs +75 -0
  83. package/engine/commands/swarm.cjs +75 -0
  84. package/engine/commands/telegram.cjs +32 -0
  85. package/engine/commands/uninstall.cjs +68 -0
  86. package/engine/commands/update.cjs +54 -0
  87. package/engine/commands/upload.cjs +18 -0
  88. package/engine/commands/usage.cjs +35 -0
  89. package/engine/commands/variant.cjs +25 -0
  90. package/engine/commands/version.cjs +9 -0
  91. package/engine/commands/whoami.cjs +38 -0
  92. package/engine/commands/workforce.cjs +103 -0
  93. package/engine/core/db.cjs +160 -0
  94. package/engine/core/paths.cjs +35 -0
  95. package/engine/experience/build.cjs +181 -0
  96. package/engine/experience/intents.cjs +492 -0
  97. package/engine/experience/runtime.cjs +242 -0
  98. package/engine/experience/variant.cjs +196 -0
  99. package/engine/firms/orchestrate.cjs +333 -0
  100. package/engine/hephaestus/runtime.cjs +697 -0
  101. package/engine/hub/install.cjs +872 -0
  102. package/engine/hub/plugins.cjs +213 -0
  103. package/engine/mcp/consent.cjs +289 -0
  104. package/engine/mcp/contract.cjs +202 -0
  105. package/engine/mcp/index.cjs +43 -0
  106. package/engine/mcp/inventory.cjs +322 -0
  107. package/engine/mcp/plan.cjs +286 -0
  108. package/engine/mcp/probe.cjs +151 -0
  109. package/engine/memory-cli/curate.cjs +163 -0
  110. package/engine/oberon/common.cjs +69 -0
  111. package/engine/oberon/manifest.cjs +164 -0
  112. package/engine/oberon/outputs.cjs +70 -0
  113. package/engine/oberon/render.cjs +164 -0
  114. package/engine/project/career-graph.cjs +249 -0
  115. package/engine/project/credentials.cjs +262 -0
  116. package/engine/project/env-file.cjs +46 -0
  117. package/engine/project/index.cjs +27 -0
  118. package/engine/project/memory-context.cjs +453 -0
  119. package/engine/project/ontology.cjs +467 -0
  120. package/engine/project/paths.cjs +39 -0
  121. package/engine/project/seed.cjs +200 -0
  122. package/engine/project/state.cjs +403 -0
  123. package/engine/project/super-ontology-seed.json +3288 -0
  124. package/engine/runtimes/detect.cjs +54 -0
  125. package/engine/runtimes/overrides.cjs +139 -0
  126. package/engine/runtimes/resolve.cjs +64 -0
  127. package/engine/sessions/apply-fences.cjs +188 -0
  128. package/engine/sessions/fences.cjs +362 -0
  129. package/engine/sessions/orchestrator.cjs +170 -0
  130. package/engine/sessions/prompt.cjs +212 -0
  131. package/engine/sessions/session.cjs +245 -0
  132. package/engine/sessions/sink.cjs +54 -0
  133. package/engine/sessions/store.cjs +79 -0
  134. package/engine/storm/deps.cjs +88 -0
  135. package/engine/storm/storm.cjs +218 -0
  136. package/engine/storm/swarm.cjs +422 -0
  137. package/engine/ui/palette.cjs +105 -0
  138. package/engine/ui/renderer.cjs +85 -0
  139. package/engine/ui/repl.cjs +444 -0
  140. package/engine/workforce/capture.cjs +701 -0
  141. package/engine/workforce/deps.cjs +472 -0
  142. package/package.json +2 -6
  143. package/engine/agentlas-experience-mcp.cjs +0 -1709
  144. package/engine/agentlas-parity.cjs +0 -1499
  145. package/engine/agentlas-repl.cjs +0 -1780
@@ -201,21 +201,23 @@ class Ui {
201
201
  this._turnChrome = null;
202
202
  this._footerDrawn = false;
203
203
  this._footerDrawnRows = 0;
204
+ this._footerDrawnWidths = [];
205
+ this._footerViewportRows = 0;
206
+ this._footerScrollBottom = 0;
204
207
  this._footerSuspended = false;
205
208
  this._resumeSpinnerAfterStream = false;
206
209
  this._streamKeepsFooter = false;
207
210
  this._turnTasks = [];
208
- this._tasksExpanded = true;
211
+ this._tasksExpanded = false;
209
212
  this._turnKeyHandler = null;
210
213
  this._turnInputWasRaw = false;
214
+ this._turnResizeHandler = null;
215
+ this._turnStatusShown = false;
211
216
  }
212
217
 
213
218
  write(s) {
214
- const redrawFooter = !!(this._turnChrome && !this._footerSuspended);
215
- if (redrawFooter) this._eraseFooter();
216
219
  this.out.write(s);
217
220
  if (s.length) this._atLineStart = s.endsWith("\n");
218
- if (redrawFooter) this._drawFooter();
219
221
  }
220
222
  line(s = "") {
221
223
  if (!this._turnChrome) this.stopSpinner();
@@ -255,7 +257,7 @@ class Ui {
255
257
  const plain = truncateCells(`${status} ${meta}`, available);
256
258
  const statusLine = this.c.emerald(frame + " ") + this.c.text(plain);
257
259
  const taskLines = [];
258
- if (this._turnTasks.length) {
260
+ if (this._turnTasks.length || this._tasksExpanded) {
259
261
  const completed = this._turnTasks.filter((task) => task.status === "completed").length;
260
262
  const toggle = this._tasksExpanded ? this.t("tasks.hide") : this.t("tasks.show");
261
263
  taskLines.push(this.c.bold(this.c.text(`${this.t("tasks.title")} ${completed}/${this._turnTasks.length}`)) + this.c.faint(` · ${toggle}`));
@@ -288,45 +290,41 @@ class Ui {
288
290
  }
289
291
 
290
292
  _eraseFooter() {
291
- if (!this._footerDrawn) return;
292
- const rows = this._footerDrawnRows;
293
- let seq = "\r";
294
- if (rows > 1) seq += `\x1b[${rows - 1}A`;
295
- seq += "\x1b[0J";
296
- this.out.write(seq);
297
293
  this._footerDrawn = false;
298
294
  this._footerDrawnRows = 0;
295
+ this._footerDrawnWidths = [];
296
+ this._footerViewportRows = 0;
297
+ }
298
+
299
+ _setFooterScrollRegion(footerRows) {
300
+ void footerRows;
301
+ }
302
+
303
+ _resetFooterScrollRegion() {
304
+ this._footerScrollBottom = 0;
299
305
  }
300
306
 
301
307
  _drawFooter() {
302
- if (!this._turnChrome || this._footerSuspended || this._footerDrawn || !this.out.isTTY) return;
303
- const lines = this._footerLines();
304
- if (!lines.length) return;
305
- if (!this._atLineStart) this.out.write("\n");
306
- this.out.write(lines.join("\n"));
307
- this._footerDrawn = true;
308
- this._footerDrawnRows = lines.length;
308
+ // Deliberately append-only during active turns. Multi-row live footers are
309
+ // not scrollback-safe across tmux/macOS resize reflow: saved cursors,
310
+ // relative erasure, absolute rows, and scroll regions can all either leave
311
+ // ghosts or discard real output. The composer returns after the turn.
309
312
  }
310
313
 
311
314
  _redrawFooter() {
312
- if (!this._turnChrome || this._footerSuspended) return;
313
- this._eraseFooter();
314
- this._drawFooter();
315
+ // Active-turn output is append-only; resize requires no repaint.
315
316
  }
316
317
 
317
318
  // ── 스피너 (stderr가 아닌 메인 스트림에, 같은 줄을 갱신) ──
318
319
  startSpinner(text) {
319
320
  if (this._turnChrome) {
320
321
  this._spinText = text || this._spinText || "";
321
- if (this._spinTimer) return;
322
- this._spinStart = Date.now();
323
- const tick = () => {
324
- this._spinFrame++;
325
- this._redrawFooter();
326
- };
327
- tick();
328
- this._spinTimer = setInterval(tick, 120);
329
- if (this._spinTimer.unref) this._spinTimer.unref();
322
+ if (!this._turnStatusShown && this._spinText) {
323
+ this._turnStatusShown = true;
324
+ this._spinStart = Date.now();
325
+ const stop = this.lang === "ko" ? "Ctrl-C로 중단" : "Ctrl-C to interrupt";
326
+ this.info(`${this._spinText} · ${stop}`);
327
+ }
330
328
  return;
331
329
  }
332
330
  if (!this.enabled || !this.out.isTTY) {
@@ -360,21 +358,28 @@ class Ui {
360
358
  this._turnFailures = 0;
361
359
  this._lastTool = null;
362
360
  this._turnTasks = [];
363
- this._tasksExpanded = true;
361
+ this._tasksExpanded = false;
362
+ this._spinText = chrome && typeof chrome === "object" && typeof chrome.activity === "string"
363
+ ? chrome.activity
364
+ : "";
365
+ this._spinFrame = 0;
366
+ this._turnStatusShown = false;
364
367
  if (chrome && this.out.isTTY) {
365
368
  this._turnChrome = typeof chrome === "string" ? { status: chrome } : { ...chrome };
366
- this._drawFooter();
367
369
  this._attachTurnKeys();
368
370
  }
369
371
  }
370
372
  endTurn() {
371
373
  this.stopSpinner(true);
372
374
  this._eraseFooter();
375
+ this._resetFooterScrollRegion();
373
376
  this._detachTurnKeys();
377
+ this._detachTurnResize();
374
378
  this._turnChrome = null;
375
379
  this._footerSuspended = false;
376
380
  this._turnStart = null;
377
381
  this._turnTasks = [];
382
+ this._turnStatusShown = false;
378
383
  }
379
384
 
380
385
  _attachTurnKeys() {
@@ -386,7 +391,7 @@ class Ui {
386
391
  const handler = (_str, key = {}) => {
387
392
  if (key.ctrl && String(key.name || "").toLowerCase() === "t") {
388
393
  this._tasksExpanded = !this._tasksExpanded;
389
- this._redrawFooter();
394
+ this._printTaskSnapshot();
390
395
  return;
391
396
  }
392
397
  if (key.ctrl && String(key.name || "").toLowerCase() === "c" && this._turnChrome?.onInterrupt) {
@@ -405,25 +410,58 @@ class Ui {
405
410
  try { if (input?.setRawMode) input.setRawMode(this._turnInputWasRaw); } catch { /* ignore */ }
406
411
  }
407
412
 
413
+ _attachTurnResize() {
414
+ const out = this.out;
415
+ if (this._turnResizeHandler || !out || typeof out.on !== "function") return;
416
+ this._turnResizeHandler = () => this._redrawFooter();
417
+ out.on("resize", this._turnResizeHandler);
418
+ }
419
+
420
+ _detachTurnResize() {
421
+ const out = this.out;
422
+ if (this._turnResizeHandler && out && typeof out.removeListener === "function") {
423
+ out.removeListener("resize", this._turnResizeHandler);
424
+ }
425
+ this._turnResizeHandler = null;
426
+ }
427
+
428
+ _printTaskSnapshot() {
429
+ if (!this._tasksExpanded) {
430
+ this.info(this.lang === "ko" ? "작업 상세를 숨겼습니다." : "Task details hidden.");
431
+ return;
432
+ }
433
+ const completed = this._turnTasks.filter((task) => task.status === "completed").length;
434
+ this.line("");
435
+ this.info(`${this.t("tasks.title")} ${completed}/${this._turnTasks.length}`);
436
+ for (const task of this._turnTasks.slice(-8)) {
437
+ const icon = task.status === "completed" ? "✓" : task.status === "failed" ? "!" : task.status === "in_progress" ? "■" : "□";
438
+ const statusKey = task.status === "completed"
439
+ ? "tasks.done"
440
+ : task.status === "failed"
441
+ ? "tasks.failed"
442
+ : task.status === "in_progress"
443
+ ? "tasks.progress"
444
+ : "tasks.pending";
445
+ this.info(`${icon} ${task.label} · ${this.t(statusKey)}`);
446
+ }
447
+ }
448
+
408
449
  replaceTasks(payload, source) {
409
450
  const normalized = taskEvents.normalizeTaskList(payload, source);
410
451
  if (!normalized.length && !Array.isArray(payload) && !Array.isArray(payload?.todos) && !Array.isArray(payload?.items) && !Array.isArray(payload?.tasks)) return;
411
452
  this._turnTasks = normalized;
412
- this._redrawFooter();
413
453
  }
414
454
 
415
455
  applyTaskTool(name, payload, toolId) {
416
456
  const next = taskEvents.applyTaskTool(this._turnTasks, name, payload, toolId);
417
457
  if (next === this._turnTasks) return;
418
458
  this._turnTasks = next;
419
- this._redrawFooter();
420
459
  }
421
460
 
422
461
  applyTaskResult(name, payload, toolId) {
423
462
  const next = taskEvents.applyTaskResult(this._turnTasks, name, payload, toolId);
424
463
  if (next === this._turnTasks) return;
425
464
  this._turnTasks = next;
426
- this._redrawFooter();
427
465
  }
428
466
  updateSpinner(text) {
429
467
  this._spinText = text || "";
@@ -462,7 +500,6 @@ class Ui {
462
500
  this._resumeSpinnerAfterStream = !!this._spinTimer;
463
501
  this.stopSpinner(true);
464
502
  if (this._turnChrome) {
465
- this._eraseFooter();
466
503
  this._footerSuspended = true;
467
504
  }
468
505
  this.ensureNl();
@@ -485,7 +522,6 @@ class Ui {
485
522
  }
486
523
  if (this._turnChrome) {
487
524
  this._footerSuspended = false;
488
- this._drawFooter();
489
525
  if (this._resumeSpinnerAfterStream) this.startSpinner(this._spinText);
490
526
  }
491
527
  this._resumeSpinnerAfterStream = false;
@@ -535,20 +571,30 @@ class Ui {
535
571
  status(msg) {
536
572
  this.updateSpinner(msg);
537
573
  }
574
+ _message(prefix, prefixPaint, messagePaint, msg) {
575
+ const { wrapWidth } = require("./agentlas-composer.cjs");
576
+ const columns = Math.max(8, Number(this.out.columns) || 80);
577
+ const prefixWidth = visibleWidth(prefix);
578
+ const lines = wrapWidth(stripAnsi(String(msg ?? "")), Math.max(2, columns - prefixWidth));
579
+ lines.forEach((line, index) => {
580
+ const lead = index === 0 ? prefixPaint(prefix) : " ".repeat(prefixWidth);
581
+ this.line(lead + messagePaint(line));
582
+ });
583
+ }
538
584
  info(msg) {
539
- this.line(this.c.dim(" " + msg));
585
+ this._message(" ", this.c.dim, this.c.dim, msg);
540
586
  }
541
587
  ok(msg) {
542
588
  this.stopSpinner();
543
- this.line(this.c.green("✓ ") + this.c.text(msg));
589
+ this._message("✓ ", this.c.green, this.c.text, msg);
544
590
  }
545
591
  warn(msg) {
546
592
  this.stopSpinner();
547
- this.line(this.c.amber("! ") + this.c.text(msg));
593
+ this._message("! ", this.c.amber, this.c.text, msg);
548
594
  }
549
595
  error(msg) {
550
596
  this.stopSpinner();
551
- this.line(this.c.paw("✗ ") + this.c.text(msg));
597
+ this._message("✗ ", this.c.paw, this.c.text, msg);
552
598
  }
553
599
 
554
600
  // 최종 텍스트(비스트리밍 경로)에 가벼운 마크다운 강조 적용 후 출력.
@@ -577,6 +623,11 @@ class Ui {
577
623
  cost(usage) {
578
624
  this._lastUsage = usage || null;
579
625
  if (!usage) return;
626
+ // During an active turn, usage remains available to the composer/session
627
+ // ledger. Printing it into the transcript would look like model output.
628
+ if (this._turnChrome) {
629
+ return;
630
+ }
580
631
  const bits = [];
581
632
  if (usage.input_tokens != null || usage.output_tokens != null) {
582
633
  bits.push(`${usage.input_tokens ?? "?"}→${usage.output_tokens ?? "?"} tok`);