agentlas 1.0.11 → 1.0.12

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 CHANGED
@@ -1,5 +1,33 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.12 — 2026-07-28
4
+
5
+ - **Orchestrator/worker model roles now resolve from ordered candidate
6
+ pools.** The shared `model_role_members` table (Desktop schema v80) holds
7
+ n candidates per role in priority order; the terminal picks the first
8
+ member that is actually executable here, records every skipped member
9
+ with its reason, and never silently substitutes a lower-priority runtime
10
+ when all members are unavailable — the head member is used and the skip
11
+ list is preserved. An empty worker pool inherits the orchestrator pool,
12
+ matching the single-row inherit contract, and databases without pools
13
+ keep resolving through the v79 single-row and legacy `active_runtime`
14
+ ladders unchanged.
15
+ - **Workforce escalation is bounded and receipted end to end.** A worker
16
+ that violates the handoff output contract twice — or is named in two
17
+ consecutive verifier failures — gets exactly one orchestrator-role
18
+ retry, stamped with `escalated-after-failure`, the failure count, and
19
+ the attempt number; a failing escalation stops honestly instead of
20
+ looping or downgrading.
21
+ - **BYOK Anthropic calls mark the system prefix as a prompt-cache
22
+ breakpoint.** Real Anthropic endpoints receive the system prompt as one
23
+ `cache_control: ephemeral` block (~90% cheaper cached input on hits;
24
+ a silent no-op below the per-model minimum). Anthropic-compatible
25
+ endpoints (GLM/Kimi/DeepSeek) keep the plain string form they expect.
26
+ - Model-allocation receipts split "no allocation was provided"
27
+ (`allocation_not_provided`) from "the allocation was malformed"
28
+ (`invalid_ai_allocation`), and real invocations now retain the
29
+ provider-reported token usage per role instead of discarding it.
30
+
3
31
  ## 1.0.11 — 2026-07-27
4
32
 
5
33
  - **The slash palette repaints in place instead of stacking copies of
@@ -582,6 +582,7 @@ function attachSlashPalette(rl, opts = {}) {
582
582
  selected: 0,
583
583
  selectedCommand: null,
584
584
  visible: false,
585
+ navigated: false,
585
586
  dismissedForLine: null,
586
587
  };
587
588
 
@@ -596,8 +597,23 @@ function attachSlashPalette(rl, opts = {}) {
596
597
  return rows().length > 0 && state.dismissedForLine !== (rl.line || "");
597
598
  }
598
599
  function replaceLine(value) {
600
+ const next = String(value || "");
601
+ /*
602
+ * keypress 리스너 안에서 rl.write(Ctrl-U) → rl.write(text)를 재진입시키면
603
+ * Node readline의 원래 Tab/Enter 핸들러가 아직 같은 키를 처리하는 중이라
604
+ * 기존 `/s` 뒤에 선택값을 붙였다(`/s/team`, `/s/skills` 실측). line/cursor는
605
+ * readline의 공개 관측 상태이고 `_refreshLine`은 그 상태를 그리는 유일한
606
+ * 부수효과라, 한 번에 교체해 재진입을 피한다. 구형 Node만 기존 키 시퀀스로
607
+ * 폴백한다.
608
+ */
609
+ if (typeof rl._refreshLine === "function") {
610
+ rl.line = next;
611
+ rl.cursor = next.length;
612
+ rl._refreshLine();
613
+ return;
614
+ }
599
615
  rl.write(null, { ctrl: true, name: "u" });
600
- rl.write(value);
616
+ rl.write(next);
601
617
  }
602
618
  /*
603
619
  * 커서 복원은 상대 이동으로만 한다.
@@ -644,8 +660,19 @@ function attachSlashPalette(rl, opts = {}) {
644
660
  });
645
661
  if (!body) { clear(); return; }
646
662
  const lines = body.split("\n");
647
- // 첫 줄바꿈은 프롬프트 아래로 내려가며, 자리가 없으면 여기서 화면이 한 번 밀린다.
648
- // 그린 만큼 그대로 되올라오므로 이후 갱신은 제자리에서 일어난다.
663
+ /*
664
+ * 줄바꿈은 프롬프트 아래로 내려가며, 자리가 없으면 여기서 화면이 한 번 밀린다.
665
+ * 그린 만큼 그대로 되올라오므로 이후 갱신은 제자리에서 일어난다.
666
+ *
667
+ * 복귀 후에는 커서 열만 맞춘다. readline 의 prompt(true) 로 프롬프트 줄을 다시
668
+ * 그리면 refreshLine 이 커서 아래를 지워 방금 그린 프레임까지 함께 날아간다
669
+ * (실측: 리사이즈 없이도 팔레트가 통째로 사라짐). 프롬프트 줄 자체는 지운 적이
670
+ * 없으므로 평상시에는 화면에 그대로 남아 있다.
671
+ *
672
+ * 남은 한계: 창 크기를 줄이면 터미널이 프롬프트 줄을 리플로우하며 지울 수 있고,
673
+ * 그때는 다음 입력 전까지 프롬프트가 보이지 않는다(40행→18행 축소에서 실측).
674
+ * 팔레트는 리사이즈를 구독하지 않는다.
675
+ */
649
676
  stream.write(`\r\n\x1b[0J${lines.join("\r\n")}\x1b[${lines.length}A\x1b[${promptColumn()}G`);
650
677
  state.visible = true;
651
678
  }
@@ -667,6 +694,7 @@ function attachSlashPalette(rl, opts = {}) {
667
694
  if (!list.length) return false;
668
695
  state.selected = (state.selected + delta + list.length) % list.length;
669
696
  state.selectedCommand = list[state.selected].command;
697
+ state.navigated = true;
670
698
  const query = rl.line || "";
671
699
  setImmediate(() => {
672
700
  if ((rl.line || "") !== query) replaceLine(query);
@@ -695,12 +723,38 @@ function attachSlashPalette(rl, opts = {}) {
695
723
  move(name === "down" ? 1 : -1);
696
724
  return;
697
725
  }
698
- // Shift-Tab 은 팔레트 확정 키가 아니다 호출자(REPL)의 권한 순환 단축키다.
699
- // 여기서 select() 하면 번의 Shift-Tab 내용까지 바꿔 버린다.
700
- if (active() && ((name === "tab" && !key.shift) || name === "return")) {
701
- select();
726
+ // Tab 은 완성이다강조된 항목으로 줄을 채운다.
727
+ // Shift-Tab 팔레트 확정 키가 아니다(호출자 REPL 권한 순환 단축키다).
728
+ if (active() && name === "tab" && !key.shift) {
729
+ if (select()) {
730
+ /*
731
+ * prependListener는 readline 자체 Tab 처리를 중단시키지 못한다. 선택을 먼저
732
+ * 반영한 뒤, 기본 완성기가 같은 키로 줄을 다시 바꿔도 다음 tick에 exact
733
+ * 선택을 한 번 재적용한다.
734
+ */
735
+ const selected = state.selectedCommand;
736
+ setImmediate(() => {
737
+ if (selected) replaceLine(selected);
738
+ });
739
+ }
740
+ return;
741
+ }
742
+ /*
743
+ * Enter 는 사용자가 실제로 목록을 훑었을 때만 강조 항목을 확정한다.
744
+ *
745
+ * 예전에는 팔레트가 떠 있기만 하면 Enter 가 무조건 select() 를 불렀고,
746
+ * 훑은 적이 없으면 state.selected 는 0이라 "목록 첫 줄"이 대신 실행됐다.
747
+ * `/s`(활성 세션 전환)를 치고 Enter 하면 `/sessions` 가 돌아간다 — 친 것과
748
+ * 다른 명령이 실행되는 것이다(pty 실측). 게다가 피해 대상은 팔레트 정렬의
749
+ * 함수라, 명령 목록을 손볼 때마다 어떤 명령이 가로채이는지가 조용히 바뀐다.
750
+ */
751
+ if (active() && name === "return") {
752
+ if (state.navigated) select();
753
+ else clear();
702
754
  return;
703
755
  }
756
+ // 타이핑이 이어지면 "훑었다"는 사실은 무효가 된다 — 질의가 달라졌기 때문.
757
+ state.navigated = false;
704
758
  state.dismissedForLine = null;
705
759
  setImmediate(render);
706
760
  }