@kendoo.agentdesk/agentdesk 0.32.0 → 0.33.0
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 +24 -0
- package/README.md +17 -5
- package/cli/agents.mjs +8 -8
- package/cli/daemon.mjs +63 -9
- package/cli/engine/agents/index.mjs +23 -10
- package/cli/engine/commands.mjs +162 -0
- package/cli/engine/evidence.mjs +4 -2
- package/cli/engine/hooks.mjs +94 -35
- package/cli/engine/lessons.mjs +156 -0
- package/cli/engine/phases/EXECUTION.md +5 -3
- package/cli/engine/phases/INTAKE.md +2 -1
- package/cli/engine/phases/PLAN.md +4 -3
- package/cli/engine/phases/REVIEW.md +2 -2
- package/cli/engine/phases/SOLO.md +5 -1
- package/cli/engine/phases/SUMMARY.md +5 -4
- package/cli/engine/prompts.mjs +17 -10
- package/cli/engine/recovery.mjs +101 -0
- package/cli/engine/schemas.mjs +39 -8
- package/cli/engine/session.mjs +206 -51
- package/cli/engine/tracker/github.md +1 -1
- package/cli/engine/tracker/jira.md +1 -1
- package/cli/engine/tracker/linear.md +1 -1
- package/cli/engine/verdict.mjs +2 -2
- package/cli/prompt.mjs +5 -12
- package/cli/session-queue.mjs +3 -1
- package/package.json +4 -2
- package/shared/recovery.mjs +28 -0
- package/shared/session-status.mjs +1 -1
package/cli/prompt.mjs
CHANGED
|
@@ -42,16 +42,9 @@ export function loadProjectMemory(cwd) {
|
|
|
42
42
|
return "";
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
// Notes earlier teams wrote by hand into .agentdesk/memory.md. Still shown,
|
|
46
|
+
// no longer written: lessons are recorded by the engine from the SUMMARY
|
|
47
|
+
// handoff (cli/engine/lessons.mjs), each with its source and a status.
|
|
48
|
+
export const LEGACY_NOTES_HEADER = `## LEGACY PROJECT NOTES (read-only)
|
|
47
49
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
**When to save**: After discovering something non-obvious that cost time (test setup steps, required seed data, login credentials for test env, workarounds, environment quirks, deployment steps). If you had to figure it out, save it so you don't have to next time.
|
|
51
|
-
|
|
52
|
-
**When NOT to save**: Code patterns, architecture, or anything derivable from the codebase. Don't duplicate what's already in README or CLAUDE.md.
|
|
53
|
-
|
|
54
|
-
**Format**: Use clear markdown sections. Update existing sections rather than appending duplicates. Never store real secrets — reference env vars instead (e.g. \`$TEST_ADMIN_PASSWORD\`).
|
|
55
|
-
|
|
56
|
-
**How**: Use the Edit or Write tool on \`.agentdesk/memory.md\`. Create the file if it doesn't exist.
|
|
57
|
-
`.trim();
|
|
50
|
+
Notes earlier teams left by hand in \`.agentdesk/memory.md\`. Treat them as hints to verify, not as facts. Do not edit that file — lessons are now recorded by the engine from the SUMMARY handoff (\`lessons\` / \`retireLessons\`).`;
|
package/cli/session-queue.mjs
CHANGED
|
@@ -7,7 +7,7 @@ export function sessionLimit(value = process.env.AGENTDESK_MAX_SESSIONS) {
|
|
|
7
7
|
|
|
8
8
|
// Capacity belongs to the daemon, not the network connection or UI status.
|
|
9
9
|
// Hold reservations through confirmation, cancellation and engine teardown.
|
|
10
|
-
export function createSessionQueue({ limit = sessionLimit(), run, onQueued = () => {}, onError = () => {} }) {
|
|
10
|
+
export function createSessionQueue({ limit = sessionLimit(), run, onQueued = () => {}, onError = () => {}, onSettled = () => {} }) {
|
|
11
11
|
const active = new Map();
|
|
12
12
|
const waiting = [];
|
|
13
13
|
let closed = false;
|
|
@@ -20,6 +20,7 @@ export function createSessionQueue({ limit = sessionLimit(), run, onQueued = ()
|
|
|
20
20
|
active.set(job.sessionId, job);
|
|
21
21
|
Promise.resolve().then(() => run(job)).catch(error => onError(job, error)).finally(() => {
|
|
22
22
|
active.delete(job.sessionId);
|
|
23
|
+
onSettled(job);
|
|
23
24
|
drain();
|
|
24
25
|
});
|
|
25
26
|
}
|
|
@@ -39,6 +40,7 @@ export function createSessionQueue({ limit = sessionLimit(), run, onQueued = ()
|
|
|
39
40
|
waiting.splice(index, 1);
|
|
40
41
|
return true;
|
|
41
42
|
},
|
|
43
|
+
get(sessionId) { return active.get(sessionId) || waiting.find(job => job.sessionId === sessionId); },
|
|
42
44
|
get activeIds() { return [...active.keys()]; },
|
|
43
45
|
get queuedIds() { return waiting.map(job => job.sessionId); },
|
|
44
46
|
close() { closed = true; waiting.length = 0; },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kendoo.agentdesk/agentdesk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
4
4
|
"description": "AI team orchestrator for Claude Code — run collaborative agent sessions from your terminal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -22,7 +22,9 @@
|
|
|
22
22
|
"server": "node server/index.mjs",
|
|
23
23
|
"build": "vite build",
|
|
24
24
|
"preview": "vite preview",
|
|
25
|
-
"test": "node --test
|
|
25
|
+
"test:sdk-handoff": "node --test --test-concurrency=1 --test-reporter=spec tests/engine-sdk-handoff.smoke.mjs",
|
|
26
|
+
"test:sdk-leadership": "node --test --test-concurrency=1 --test-reporter=spec tests/engine-sdk-leadership.smoke.mjs",
|
|
27
|
+
"test": "node --test tests/server.test.mjs tests/agents.test.mjs tests/homepage.test.mjs tests/sessionUtils.test.mjs tests/tracker-url.test.mjs tests/session-preflight.test.mjs tests/access.test.mjs tests/project-ownership.test.mjs tests/random-hex.test.mjs tests/projects-registry.test.mjs tests/phase-loop.test.mjs tests/proc.test.mjs tests/crypto.test.mjs tests/dotenv.test.mjs tests/update-check.test.mjs tests/setup-helpers.test.mjs tests/project-key.test.mjs tests/tracker-project.test.mjs tests/tracker-check.test.mjs tests/config.test.mjs tests/engine-env.test.mjs tests/engine-events.test.mjs tests/engine-verdict.test.mjs tests/engine-hooks.test.mjs tests/engine-commands.test.mjs tests/engine-agents.test.mjs tests/session-isolation.test.mjs tests/engine-session.test.mjs tests/engine-prompts.test.mjs tests/engine-schemas.test.mjs tests/engine-claude-auth.test.mjs tests/worktrees.test.mjs tests/workspaces-api.test.mjs tests/engine-outcome.test.mjs tests/session-outcomes.test.mjs tests/outcome-hydration.test.mjs tests/mobile-outcomes.test.mjs tests/session-queue.test.mjs tests/useFollowScroll.test.mjs tests/session-usage.test.mjs tests/task-lookup.test.mjs tests/engine-evidence.test.mjs tests/engine-handoff.test.mjs tests/engine-team-profile.test.mjs tests/project-settings.test.mjs tests/delivery.test.mjs tests/feed-view.test.mjs tests/recovery.test.mjs tests/session-recovery-api.test.mjs tests/engine-lessons.test.mjs",
|
|
26
28
|
"test:coverage": "node --test --experimental-test-coverage --test-coverage-include='cli/**' --test-coverage-include='server/**' --test-coverage-lines=60 --test-coverage-branches=62 tests/*.test.mjs",
|
|
27
29
|
"lint": "eslint .",
|
|
28
30
|
"lint:fix": "eslint . --fix",
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Public recovery state contains no credentials or raw tool responses.
|
|
2
|
+
export const RECOVERY_STATES = new Set(["running", "recovering", "pausing", "paused", "waiting_access", "waiting_input"]);
|
|
3
|
+
|
|
4
|
+
export function classifyFailure(text = "", code = "") {
|
|
5
|
+
const detail = `${code} ${text}`;
|
|
6
|
+
if (/401|oauth.*revoked|failed to authenticate|not.logged.in|authentication|invalid.api.key/i.test(detail)) {
|
|
7
|
+
return { state: "waiting_access", kind: "authentication", message: "The model connection needs attention. Work has been preserved. Reconnect on the daemon machine, then verify and resume." };
|
|
8
|
+
}
|
|
9
|
+
if (/permission|not.allowed|denied|403/i.test(detail)) {
|
|
10
|
+
return { state: "waiting_access", kind: "permission", message: "A required operation was denied. Check project access or correct the instructions, then retry." };
|
|
11
|
+
}
|
|
12
|
+
if (/handoff|structured/i.test(detail)) {
|
|
13
|
+
return { state: "waiting_input", kind: "handoff", message: "The phase handoff could not be recovered. Review the preserved findings before retrying." };
|
|
14
|
+
}
|
|
15
|
+
return { state: "waiting_input", kind: "execution", message: "Work paused after an execution failure. Review the details, correct instructions or the environment, then retry." };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function normalizeRecovery(value) {
|
|
19
|
+
if (!value || !RECOVERY_STATES.has(value.state)) return null;
|
|
20
|
+
return {
|
|
21
|
+
state: value.state,
|
|
22
|
+
kind: String(value.kind || "execution").slice(0, 60),
|
|
23
|
+
message: String(value.message || "").slice(0, 1500),
|
|
24
|
+
phase: String(value.phase || "").slice(0, 30),
|
|
25
|
+
ready: value.ready === true,
|
|
26
|
+
updatedAt: Date.now(),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Running consumes execution capacity. Open also includes queued work and a
|
|
2
2
|
// human handoff: neither may disappear through generic inactive cleanup.
|
|
3
3
|
export const RUNNING_SESSION_STATUSES = new Set(["active", "stale"]);
|
|
4
|
-
export const OPEN_SESSION_STATUSES = new Set(["queued", "active", "stale", "handoff"]);
|
|
4
|
+
export const OPEN_SESSION_STATUSES = new Set(["queued", "active", "stale", "handoff", "paused"]);
|
|
5
5
|
export const isRunningSession = status => RUNNING_SESSION_STATUSES.has(status);
|
|
6
6
|
export const isOpenSession = status => OPEN_SESSION_STATUSES.has(status);
|