@dotdrelle/wiki-manager 0.14.13 → 0.14.16
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/.env.example +11 -0
- package/docker-compose.yml +1 -1
- package/package.json +1 -1
- package/src/activity/activityAggregator.js +43 -13
- package/src/activity/activityAggregator.test.js +51 -2
- package/src/agent/graph.js +79 -11
- package/src/agent/graph.test.js +43 -3
- package/src/cli/wiki-manager.js +44 -3
- package/src/commands/slash.js +10 -3
- package/src/commands/slash.test.js +24 -0
- package/src/core/buildInfo.json +2 -2
- package/src/core/dockerCompose.test.js +4 -0
- package/src/core/env.test.js +3 -0
- package/src/core/mcp.js +1 -1
- package/src/core/wikiSetup.js +35 -0
- package/src/core/wikiWorkspace.test.js +20 -0
- package/src/core/workspaces.js +10 -2
- package/src/orchestrator/dependencyResolver.js +19 -1
- package/src/orchestrator/objectiveResolver.js +24 -0
- package/src/orchestrator/objectiveResolver.test.js +23 -1
- package/src/orchestrator/scheduler.test.js +22 -1
- package/src/runtime/auth.test.js +65 -1
- package/src/runtime/client.js +4 -0
- package/src/runtime/donna-contract.test.js +2 -0
- package/src/runtime/lifecycle.js +21 -12
- package/src/runtime/runner.js +111 -15
- package/src/runtime/runner.test.js +30 -0
- package/src/runtime/server.js +13 -2
- package/src/runtime/server.test.js +30 -1
- package/src/shell/FileEditorDialog.tsx +2 -2
- package/src/shell/LeftPane.tsx +60 -15
- package/src/shell/RightPane.tsx +147 -54
- package/src/shell/StartupScreen.tsx +3 -7
- package/src/shell/renderer.ts +1 -0
- package/src/shell/repl.js +7 -81
- package/src/shell/repl.test.js +128 -38
- package/src/shell/tui.tsx +59 -64
- package/src/shell/useSession.ts +45 -6
- package/wiki-workspace +28 -0
package/src/shell/useSession.ts
CHANGED
|
@@ -329,6 +329,11 @@ export function useSession(props: { agent: unknown; packageJson: Record<string,
|
|
|
329
329
|
const tagged = filterRuntimeLogs(runtimeLogs.map((line: any) => `runtime ${String(line)}`), filter);
|
|
330
330
|
return [...logs(), ...tagged];
|
|
331
331
|
});
|
|
332
|
+
const pendingApprovals = createMemo(() => {
|
|
333
|
+
version();
|
|
334
|
+
return (Array.isArray(runtimeState()?.approvals) ? runtimeState().approvals : [])
|
|
335
|
+
.filter((approval: any) => approval.status === 'pending_approval');
|
|
336
|
+
});
|
|
332
337
|
|
|
333
338
|
// Index-aligned with each workspace's runtimeConversation array — not just
|
|
334
339
|
// a length count. The server sometimes finalizes a streaming placeholder
|
|
@@ -379,16 +384,23 @@ export function useSession(props: { agent: unknown; packageJson: Record<string,
|
|
|
379
384
|
continue;
|
|
380
385
|
}
|
|
381
386
|
if (role === 'user') {
|
|
382
|
-
// The user's own message was already pushed optimistically
|
|
383
|
-
//
|
|
384
|
-
//
|
|
385
|
-
//
|
|
387
|
+
// The user's own message was already pushed optimistically — either
|
|
388
|
+
// marked _pending (web / runtime-submit path, useAgent.ts) OR as a plain
|
|
389
|
+
// entry by the interactive agent turn (repl.js runAgentTurn) that then
|
|
390
|
+
// delegated. Adopt whichever already exists instead of appending a
|
|
391
|
+
// second identical copy (the delegation seeds the run with the same
|
|
392
|
+
// objective, which comes back through this merge).
|
|
386
393
|
const pendingIndex = target.findIndex((entry: any) => entry._pending && entry.role === 'user' && entry.content === content);
|
|
387
394
|
if (pendingIndex !== -1) {
|
|
388
395
|
delete target[pendingIndex]._pending;
|
|
389
396
|
backed.push(target[pendingIndex]);
|
|
390
397
|
continue;
|
|
391
398
|
}
|
|
399
|
+
const localIndex = target.findIndex((entry: any) => entry.role === 'user' && entry.content === content && !backed.includes(entry));
|
|
400
|
+
if (localIndex !== -1) {
|
|
401
|
+
backed.push(target[localIndex]);
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
392
404
|
}
|
|
393
405
|
const entry = { role, content };
|
|
394
406
|
target.push(entry);
|
|
@@ -397,19 +409,37 @@ export function useSession(props: { agent: unknown; packageJson: Record<string,
|
|
|
397
409
|
}
|
|
398
410
|
|
|
399
411
|
function syncRuntimeState() {
|
|
400
|
-
|
|
412
|
+
const workspace = (session as any).workspace ?? null;
|
|
413
|
+
const workspaceKey = workspace ?? '__global__';
|
|
414
|
+
if (runtimeSyncInFlight.has(workspaceKey)) return;
|
|
415
|
+
runtimeSyncInFlight.add(workspaceKey);
|
|
416
|
+
void fetchRuntimeState({ url: props.runtime.url, workspace })
|
|
401
417
|
.then((state) => {
|
|
418
|
+
if (((session as any).workspace ?? null) !== workspace) return;
|
|
402
419
|
const displayState = sanitizeRuntimeStateForDisplay(state);
|
|
403
420
|
setRuntimeState(displayState);
|
|
421
|
+
// The per-job "Job terminé" lines and the canned plan summary are gone:
|
|
422
|
+
// the runtime now emits ONE natural-language Donna message at completion
|
|
423
|
+
// (see announceRunOutcome in runner.js), which arrives through the
|
|
424
|
+
// conversation merge below. Detect that the chat grew to keep the
|
|
425
|
+
// welcome-hidden / scroll-to-latest behavior.
|
|
426
|
+
const beforeLength = conversationMessages(session).length;
|
|
404
427
|
mergeRuntimeConversation(displayState);
|
|
428
|
+
if (conversationMessages(session).length > beforeLength) {
|
|
429
|
+
setShowWelcome(false);
|
|
430
|
+
setConversationScroll(0);
|
|
431
|
+
}
|
|
405
432
|
setRuntimeStatus('connected');
|
|
406
433
|
refresh();
|
|
407
434
|
})
|
|
408
435
|
.catch(() => {
|
|
436
|
+
if (((session as any).workspace ?? null) !== workspace) return;
|
|
409
437
|
setRuntimeStatus('disconnected');
|
|
410
438
|
refresh();
|
|
411
|
-
})
|
|
439
|
+
})
|
|
440
|
+
.finally(() => { runtimeSyncInFlight.delete(workspaceKey); });
|
|
412
441
|
}
|
|
442
|
+
const runtimeSyncInFlight = new Set<string>();
|
|
413
443
|
let runtimeStreamAbort: AbortController | null = null;
|
|
414
444
|
let runtimeSyncDebounce: ReturnType<typeof setTimeout> | null = null;
|
|
415
445
|
let runtimeReconnectTimer: ReturnType<typeof setTimeout> | null = null;
|
|
@@ -446,6 +476,13 @@ export function useSession(props: { agent: unknown; packageJson: Record<string,
|
|
|
446
476
|
void subscribeRuntimeEvents();
|
|
447
477
|
}
|
|
448
478
|
|
|
479
|
+
// Safety net only — the SSE stream (subscribeRuntimeEvents) is the primary
|
|
480
|
+
// sync path and already debounces on every agent_event. This just catches
|
|
481
|
+
// a missed/dropped event, so it can poll far less often than that.
|
|
482
|
+
const runtimeCompletionWatchdog = setInterval(() => {
|
|
483
|
+
if (props.runtime?.url && runtimeRunStatus() === 'running') syncRuntimeState();
|
|
484
|
+
}, 10000);
|
|
485
|
+
|
|
449
486
|
let currentRuntimeWorkspace = (session as any).workspace ?? null;
|
|
450
487
|
function resyncRuntimeWorkspaceIfChanged() {
|
|
451
488
|
const workspace = (session as any).workspace ?? null;
|
|
@@ -466,6 +503,7 @@ export function useSession(props: { agent: unknown; packageJson: Record<string,
|
|
|
466
503
|
runtimeStreamAbort?.abort();
|
|
467
504
|
if (runtimeSyncDebounce) clearTimeout(runtimeSyncDebounce);
|
|
468
505
|
if (runtimeReconnectTimer) clearTimeout(runtimeReconnectTimer);
|
|
506
|
+
clearInterval(runtimeCompletionWatchdog);
|
|
469
507
|
});
|
|
470
508
|
|
|
471
509
|
const activityPollTimer = setInterval(() => {
|
|
@@ -690,6 +728,7 @@ export function useSession(props: { agent: unknown; packageJson: Record<string,
|
|
|
690
728
|
toggleRightTab,
|
|
691
729
|
selectRightTab,
|
|
692
730
|
plan,
|
|
731
|
+
pendingApprovals,
|
|
693
732
|
conversationScroll,
|
|
694
733
|
scrollConversation,
|
|
695
734
|
conversationBusy,
|
package/wiki-workspace
CHANGED
|
@@ -95,6 +95,7 @@ Commands:
|
|
|
95
95
|
agents down Stop all external agents
|
|
96
96
|
agents logs [args...] Follow external agent logs
|
|
97
97
|
agents pull Pull latest external agent images
|
|
98
|
+
agents refresh Update only external agents currently running
|
|
98
99
|
agents status Check reachability of configured MCP endpoints
|
|
99
100
|
|
|
100
101
|
runtime up Start the single host agent-runtime on Node.js 22
|
|
@@ -276,6 +277,10 @@ agents_compose() {
|
|
|
276
277
|
[[ $# -eq 0 ]] || die "agents pull does not take arguments"
|
|
277
278
|
_agents_dc pull
|
|
278
279
|
;;
|
|
280
|
+
refresh)
|
|
281
|
+
[[ $# -eq 0 ]] || die "agents refresh does not take arguments"
|
|
282
|
+
refresh_running_services 'No running external agent containers to refresh' 'Refreshed running agents: %s' _agents_dc
|
|
283
|
+
;;
|
|
279
284
|
status)
|
|
280
285
|
[[ $# -eq 0 ]] || die "agents status does not take arguments"
|
|
281
286
|
if [[ ! -f "$MANAGER_ENDPOINTS_FILE" ]]; then
|
|
@@ -751,10 +756,30 @@ read_lines_into_array() {
|
|
|
751
756
|
eval "$array_name=()"
|
|
752
757
|
local line
|
|
753
758
|
while IFS= read -r line; do
|
|
759
|
+
[[ -n "${line//[[:space:]]/}" ]] || continue
|
|
754
760
|
eval "$array_name+=(\"\$line\")"
|
|
755
761
|
done < <("$@")
|
|
756
762
|
}
|
|
757
763
|
|
|
764
|
+
# Shared by the "agents refresh" and per-workspace "refresh" subcommands:
|
|
765
|
+
# pull and recreate only the compose services already running, skipping the
|
|
766
|
+
# rest. "$@" is the compose invocation (e.g. `_agents_dc` or
|
|
767
|
+
# `compose_for_workspace "$workspace"`) to run ps/pull/up through.
|
|
768
|
+
refresh_running_services() {
|
|
769
|
+
local no_running_msg="$1"
|
|
770
|
+
local refreshed_msg_fmt="$2"
|
|
771
|
+
shift 2
|
|
772
|
+
local running_services=()
|
|
773
|
+
read_lines_into_array running_services "$@" ps --status running --services
|
|
774
|
+
if [[ ${#running_services[@]} -eq 0 ]]; then
|
|
775
|
+
printf '%s\n' "$no_running_msg"
|
|
776
|
+
return
|
|
777
|
+
fi
|
|
778
|
+
"$@" pull "${running_services[@]}"
|
|
779
|
+
"$@" up -d "${running_services[@]}"
|
|
780
|
+
printf "$refreshed_msg_fmt\n" "${running_services[*]}"
|
|
781
|
+
}
|
|
782
|
+
|
|
758
783
|
cacert_compose_args() {
|
|
759
784
|
local compose_file="$1"
|
|
760
785
|
local override_name="$2"
|
|
@@ -1074,6 +1099,9 @@ main() {
|
|
|
1074
1099
|
down)
|
|
1075
1100
|
compose_for_workspace "$workspace" down
|
|
1076
1101
|
;;
|
|
1102
|
+
refresh)
|
|
1103
|
+
refresh_running_services "No running workspace containers to refresh: $workspace" "Refreshed running workspace containers: $workspace (%s)" compose_for_workspace "$workspace"
|
|
1104
|
+
;;
|
|
1077
1105
|
logs)
|
|
1078
1106
|
local log_args=()
|
|
1079
1107
|
read_lines_into_array log_args logs_args "$@"
|