agentlas 1.0.38 → 1.0.39
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 +14 -0
- package/engine/architecture.data.json +1 -1
- package/engine/ui/pitui-shell.cjs +53 -0
- package/engine/ui/repl.cjs +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.0.39 — 2026-08-11
|
|
4
|
+
|
|
5
|
+
pi-tui shell increment 2 + architecture mirror sync.
|
|
6
|
+
|
|
7
|
+
- Experimental pi shell (`AGENTLAS_TUI=pi`): persisted history (cli-history.json
|
|
8
|
+
v2 contract), Shift-Tab permission cycling (same two-step FULL arming state
|
|
9
|
+
machine as the classic REPL), `!` shell passthrough (full-permission gate,
|
|
10
|
+
secret masking), and `/s` `/switch` `/kill` `/rm` `/sessions` `/tree` session
|
|
11
|
+
observation wired to the same orchestrator/renderer pair.
|
|
12
|
+
- Streaming display masks the Memory Events envelope (runtime contract, not
|
|
13
|
+
user-facing text); the harvest pipeline is unchanged.
|
|
14
|
+
- ARCHITECTURE_VERSION mirror synced 1.7.0 → 1.7.1 (vendor regenerated from
|
|
15
|
+
the desktop dist, value-level parity gate green).
|
|
16
|
+
|
|
3
17
|
## 1.0.38 — 2026-08-11
|
|
4
18
|
|
|
5
19
|
Silence was the worst failure mode — this release makes failures speak.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.7.
|
|
2
|
+
"version": "1.7.1",
|
|
3
3
|
"emitterBlock": "## Memory (Agentlas curated memory)\n\nAt the end of EVERY completed normal reply, emit exactly one hidden Memory Events\nenvelope. The runtime removes it before display. This envelope is the per-turn receipt:\nalways include a compact safe turn_summary, and use an empty candidates array when\nnothing durable was learned. Do not skip the envelope.\n\nRules:\n- Never include secrets, credentials, API keys, raw logs, or full transcripts.\n- Real credential values may live only in local project .env/.env.local,\n ignored signing/ or credentials/ files, or a local keychain/vault. Memory\n Events may mention env names and local relative paths only.\n- For deploy, release, store, billing, auth, API, or cloud work, first read the\n project's .agentlas/local-credentials.map.json and the top\n \"Local Credential Index\" section of .agentlas/project-soul-memory.md\n before saying a credential is missing.\n- One candidate per durable item. Keep \"content\" to one or two sentences.\n- \"memory_kind\": fact | decision | preference | risk | procedure | hypothesis | evidence | deprecation | conflict\n- \"suggested_scope\": user_identity | team_memory | project (this folder) | agent_repo | session (temporary) | discard\n- Use user_identity for a stable operator preference or personal fact (their name, role, language, tone,\n how they want you to behave) — these must outlive any one project. The curator only files user_identity\n when you label it so with \"confidence\": \"high\"; it never promotes into that scope, so a preference emitted\n at lower confidence is demoted to a throwaway session note.\n- \"agent_team\" is accepted only as a legacy alias for team_memory.\n- Add \"request_context\" when it improves future recall: user_intent, trigger_terms,\n cwd_at_request, target_project, target_path, cross_context, outcome.\n- Never put the raw user prompt or transcript in request_context.\n- Suggest a scope; the separate Memory Curator decides the final destination.\n- turn_summary is one value-free sentence about the completed outcome. It is not the\n user prompt, a transcript, raw log, secret, or absolute local path.\n\nFormat (always emit, including an empty candidates array):\n\n## Memory Events\n```json\n{\n \"schema_version\": \"agentlas.memory-ticket.v1\",\n \"turn_summary\": \"Completed outcome in one safe sentence.\",\n \"candidates\": [\n {\n \"memory_kind\": \"decision\",\n \"content\": \"...\",\n \"suggested_scope\": \"project\",\n \"confidence\": \"high\",\n \"sensitivity\": \"internal\",\n \"evidence_refs\": [],\n \"request_context\": {\n \"user_intent\": \"...\",\n \"trigger_terms\": [\"...\"],\n \"cwd_at_request\": null,\n \"target_project\": null,\n \"target_path\": null,\n \"cross_context\": false,\n \"outcome\": \"...\"\n }\n }\n ]\n}\n```",
|
|
4
4
|
"eventsHeading": "## Memory Events",
|
|
5
5
|
"memoryDir": ".agentlas",
|
|
@@ -202,6 +202,26 @@ async function startPiShell(ctx, opts = {}) {
|
|
|
202
202
|
const editor = new pi.Editor(tui, editorTheme, { autocompleteMaxVisible: 8 });
|
|
203
203
|
editor.setAutocompleteProvider(new pi.CombinedAutocompleteProvider(toSlashCommands(ctx.lang), process.cwd()));
|
|
204
204
|
|
|
205
|
+
// ── 히스토리 디스크 영속 (증분 2) — cli-history.json v2 계약을 그대로 재사용 ──
|
|
206
|
+
const input = require("../agentlas-input.cjs");
|
|
207
|
+
const historyLedger = (() => { try { return input.loadHistory(process.cwd()); } catch { return []; } })();
|
|
208
|
+
// readline 히스토리는 최신-우선 배열 — Editor에는 과거→최신 순으로 먹인다.
|
|
209
|
+
for (const entry of [...historyLedger].reverse()) editor.addToHistory(entry);
|
|
210
|
+
const recordHistory = (line) => {
|
|
211
|
+
historyLedger.unshift(line);
|
|
212
|
+
if (historyLedger.length > input.HISTORY_MAX) historyLedger.length = input.HISTORY_MAX;
|
|
213
|
+
try { input.saveHistory(historyLedger, process.cwd()); } catch { /* 히스토리는 최선노력 */ }
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// ── Shift-Tab 권한 순환 (증분 2) — repl의 순수 상태기계를 그대로 재사용 ──
|
|
217
|
+
const { createPermissionShortcut } = require("./repl.cjs");
|
|
218
|
+
const permShortcut = createPermissionShortcut({
|
|
219
|
+
lang: ctx.lang,
|
|
220
|
+
getPermission: () => permission,
|
|
221
|
+
setPermission: (level) => { permission = level; },
|
|
222
|
+
onMessage: (msg) => { ui.ensureNl(); ui.line(ui.c.dim(msg.text)); },
|
|
223
|
+
});
|
|
224
|
+
|
|
205
225
|
const commands = require("../commands/index.cjs");
|
|
206
226
|
const handleSlash = async (cmdline) => {
|
|
207
227
|
const raw = cmdline.split(/\s+/)[0] || "";
|
|
@@ -212,6 +232,26 @@ async function startPiShell(ctx, opts = {}) {
|
|
|
212
232
|
ui.line(palette.renderPalette(ctx.lang));
|
|
213
233
|
return;
|
|
214
234
|
}
|
|
235
|
+
// 세션 관찰/전환 (증분 2b) — 기본 REPL과 같은 orch/renderer 배선
|
|
236
|
+
if (cmd === "sessions" || cmd === "tree") {
|
|
237
|
+
require("./repl.cjs").printSessions(shellCtx, orch);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
if (cmd === "s" || cmd === "switch" || cmd === "kill" || cmd === "rm") {
|
|
241
|
+
const token = rest[0];
|
|
242
|
+
if (!token) { ui.line(ui.c.dim(`Usage: /${cmd} <n>`)); return; }
|
|
243
|
+
const key = String(token).startsWith("s") ? token : `s${token}`;
|
|
244
|
+
if (cmd === "kill") { orch.kill(key); return; }
|
|
245
|
+
if (cmd === "rm") {
|
|
246
|
+
orch.remove(key);
|
|
247
|
+
const act = orch.active();
|
|
248
|
+
if (act) renderer.attach(act, { replay: false });
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const session = orch.setActive(key);
|
|
252
|
+
renderer.attach(session, { replay: true });
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
215
255
|
const EXCLUDED = new Set(["firm", "setup", "run"]);
|
|
216
256
|
if (!EXCLUDED.has(cmd) && commands.COMMANDS[cmd]) {
|
|
217
257
|
await commands.COMMANDS[cmd]().run(shellCtx, rest);
|
|
@@ -229,10 +269,16 @@ async function startPiShell(ctx, opts = {}) {
|
|
|
229
269
|
const input = String(text || "").trim();
|
|
230
270
|
if (!input) return;
|
|
231
271
|
editor.addToHistory(input);
|
|
272
|
+
recordHistory(input);
|
|
232
273
|
editor.setText("");
|
|
233
274
|
ui.ensureNl();
|
|
234
275
|
ui.line(ui.c.emerald("› ") + ui.c.text(input));
|
|
235
276
|
(async () => {
|
|
277
|
+
if (input.startsWith("!")) {
|
|
278
|
+
await require("./repl.cjs").runShell(shellCtx, input.slice(1).trim(), permission)
|
|
279
|
+
.catch((e) => { if (e && (e.code || e.honestStop)) ui.error(e); else ui.error(); });
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
236
282
|
if (input.startsWith("/")) {
|
|
237
283
|
const verdict = await handleSlash(input.slice(1)).catch((e) => {
|
|
238
284
|
if (e && (e.code || e.honestStop)) ui.error(e);
|
|
@@ -265,6 +311,13 @@ async function startPiShell(ctx, opts = {}) {
|
|
|
265
311
|
};
|
|
266
312
|
|
|
267
313
|
tui.addInputListener((data) => {
|
|
314
|
+
// Shift-Tab 권한 순환 — pi-tui 가 raw mode 를 단독 소유하므로 readline 의
|
|
315
|
+
// swallowCompletion 우회 없이 여기서 직접 소비한다 (D2 위험 2의 해소 형태).
|
|
316
|
+
if (pi.matchesKey(data, "shift+tab")) {
|
|
317
|
+
permShortcut.handleKey("", { name: "tab", shift: true });
|
|
318
|
+
return { handled: true };
|
|
319
|
+
}
|
|
320
|
+
if (permShortcut.armed()) permShortcut.handleKey("", { name: "other" }); // 다른 키 = 무장 해제
|
|
268
321
|
if (pi.matchesKey(data, "ctrl+c")) {
|
|
269
322
|
const active = orch.active();
|
|
270
323
|
if (active && active.isBusy()) {
|
package/engine/ui/repl.cjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentlas",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.39",
|
|
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"
|