@dotdrelle/wiki-manager 0.14.9 → 0.14.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/.env.example +15 -1
- package/README.md +42 -2
- package/agents.docker-compose.yml +4 -5
- package/mcp.endpoints.example.json +2 -2
- package/package.json +2 -2
- package/src/agent/graph.js +8 -5
- package/src/agent/graph.test.js +4 -1
- package/src/cli/wiki-manager.js +73 -23
- package/src/commands/slash.js +33 -6
- package/src/commands/slash.test.js +17 -0
- package/src/core/buildInfo.json +2 -2
- package/src/core/cacert.js +11 -8
- package/src/core/cacert.test.js +35 -0
- package/src/core/compose.js +21 -3
- package/src/core/dockerCompose.test.js +3 -0
- package/src/core/dockerImages.js +22 -0
- package/src/core/env.js +27 -3
- package/src/core/env.test.js +72 -0
- package/src/core/mcp.js +1 -1
- package/src/core/startupCheck.js +340 -7
- package/src/core/startupCheck.test.js +190 -3
- package/src/core/wikiSetup.js +26 -2
- package/src/core/wikiWorkspace.test.js +9 -0
- package/src/runtime/lifecycle.js +1 -1
- package/src/shell/LeftPane.tsx +17 -2
- package/src/shell/RightPane.tsx +34 -17
- package/src/shell/SetupWizard.tsx +53 -10
- package/src/shell/StartupScreen.tsx +42 -9
- package/src/shell/externalLinks.js +67 -0
- package/src/shell/repl.js +149 -29
- package/src/shell/repl.test.js +187 -0
- package/src/shell/tui.tsx +60 -3
- package/wiki-workspace +20 -17
package/src/shell/tui.tsx
CHANGED
|
@@ -13,6 +13,7 @@ import { buildMcpStatus } from '../core/mcp.js';
|
|
|
13
13
|
import { loadWikircProfile, summarizeWikircConfig } from '../core/wikirc.js';
|
|
14
14
|
import { listWorkspaces } from '../core/workspaces.js';
|
|
15
15
|
import { postRuntimeShutdown } from '../runtime/client.js';
|
|
16
|
+
import { runPreflightChecks, withRuntimePreflight } from '../core/startupCheck.js';
|
|
16
17
|
|
|
17
18
|
const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
18
19
|
|
|
@@ -103,6 +104,7 @@ function App(props: {
|
|
|
103
104
|
agent: unknown;
|
|
104
105
|
packageJson: Record<string, unknown>;
|
|
105
106
|
runtime?: any;
|
|
107
|
+
preflight?: any;
|
|
106
108
|
}) {
|
|
107
109
|
const renderer = useRenderer();
|
|
108
110
|
const dimensions = useTerminalDimensions();
|
|
@@ -115,6 +117,8 @@ function App(props: {
|
|
|
115
117
|
// that invariant structural instead of relying on two booleans staying in
|
|
116
118
|
// sync at every call site.
|
|
117
119
|
const [screen, setScreen] = createSignal<'startup' | 'setup' | 'main'>('startup');
|
|
120
|
+
const [preflight, setPreflight] = createSignal(props.preflight ?? { status: 'degraded', checks: [] });
|
|
121
|
+
const [preflightBusy, setPreflightBusy] = createSignal(false);
|
|
118
122
|
let ctrlCTimer: ReturnType<typeof setTimeout> | null = null;
|
|
119
123
|
let exiting = false;
|
|
120
124
|
// Single exit path: the owned-runtime shutdown MUST happen here, on the
|
|
@@ -185,6 +189,13 @@ function App(props: {
|
|
|
185
189
|
// closeSetup() already does.
|
|
186
190
|
const loadDefaultWorkspace = async () => loadWorkspace(startupInfo(props.packageJson).workspaceName);
|
|
187
191
|
|
|
192
|
+
// The canonical status is the first useful view after entering ShellUI.
|
|
193
|
+
// Run it only after /use has established the workspace so config, services,
|
|
194
|
+
// MCP connectivity and runtime state are all reported in the same snapshot.
|
|
195
|
+
const showDefaultStatus = async (workspaceLoaded: boolean) => {
|
|
196
|
+
if (workspaceLoaded) await state.submitInput('/status');
|
|
197
|
+
};
|
|
198
|
+
|
|
188
199
|
// "Open a workspace" is really one composite action (load it, then bring
|
|
189
200
|
// its services up) — named here so it has one definition instead of being
|
|
190
201
|
// inlined as three sequential submitInput calls in openAction.
|
|
@@ -197,18 +208,60 @@ function App(props: {
|
|
|
197
208
|
return loaded;
|
|
198
209
|
};
|
|
199
210
|
|
|
211
|
+
const refreshPreflight = async () => {
|
|
212
|
+
setPreflightBusy(true);
|
|
213
|
+
try {
|
|
214
|
+
const next = await runPreflightChecks();
|
|
215
|
+
setPreflight(withRuntimePreflight(next, props.runtime));
|
|
216
|
+
} finally {
|
|
217
|
+
setPreflightBusy(false);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
200
221
|
const openAction = (action: StartupAction, workspaceName?: string) => {
|
|
201
222
|
if (action === 'init-workspace') {
|
|
202
223
|
setScreen('setup');
|
|
203
224
|
return;
|
|
204
225
|
}
|
|
226
|
+
if (action === 'retry-preflight') {
|
|
227
|
+
void refreshPreflight();
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
if (action === 'start-services') {
|
|
231
|
+
void (async () => {
|
|
232
|
+
setPreflightBusy(true);
|
|
233
|
+
try {
|
|
234
|
+
await openWorkspaceAndStartServices(workspaceName ?? startupInfo(props.packageJson).workspaceName);
|
|
235
|
+
const next = await runPreflightChecks();
|
|
236
|
+
setPreflight(withRuntimePreflight(next, props.runtime));
|
|
237
|
+
} finally {
|
|
238
|
+
setPreflightBusy(false);
|
|
239
|
+
}
|
|
240
|
+
})();
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (action === 'open-logs') {
|
|
244
|
+
setScreen('main');
|
|
245
|
+
void (async () => {
|
|
246
|
+
const loaded = await loadDefaultWorkspace();
|
|
247
|
+
if (!loaded) return;
|
|
248
|
+
const containerCheck = preflight().checks?.find((check: any) => check.kind === 'containers');
|
|
249
|
+
const service = containerCheck?.context?.unavailable?.[0];
|
|
250
|
+
if (service) await state.submitInput(`/logs ${service} 120`);
|
|
251
|
+
else await state.submitInput('/services');
|
|
252
|
+
await state.submitInput('/mcp status');
|
|
253
|
+
})();
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
205
256
|
setScreen('main');
|
|
206
257
|
void (async () => {
|
|
207
258
|
try {
|
|
208
259
|
if (action === 'open-workspace') {
|
|
209
|
-
await openWorkspaceAndStartServices(workspaceName ?? startupInfo(props.packageJson).workspaceName);
|
|
260
|
+
const loaded = await openWorkspaceAndStartServices(workspaceName ?? startupInfo(props.packageJson).workspaceName);
|
|
261
|
+
await showDefaultStatus(loaded);
|
|
210
262
|
} else if (action === 'new-conversation' || action === 'run-workflow') {
|
|
211
263
|
const loaded = await loadDefaultWorkspace();
|
|
264
|
+
await showDefaultStatus(loaded);
|
|
212
265
|
if (action === 'run-workflow' && loaded) {
|
|
213
266
|
await state.submitInput('/agent');
|
|
214
267
|
}
|
|
@@ -230,7 +283,7 @@ function App(props: {
|
|
|
230
283
|
setScreen('main');
|
|
231
284
|
// Reuse loadWorkspace (not a bare /use dispatch) so the "already on this
|
|
232
285
|
// workspace" short-circuit applies here too.
|
|
233
|
-
void loadWorkspace(info.workspaceName);
|
|
286
|
+
void loadWorkspace(info.workspaceName).then(showDefaultStatus);
|
|
234
287
|
};
|
|
235
288
|
|
|
236
289
|
const showCopyHint = (message: string) => {
|
|
@@ -397,6 +450,8 @@ function App(props: {
|
|
|
397
450
|
profileName={startup().profileName}
|
|
398
451
|
workspaces={startup().workspaces}
|
|
399
452
|
hasWorkspace={startup().hasWorkspace}
|
|
453
|
+
preflight={preflight()}
|
|
454
|
+
preflightBusy={preflightBusy()}
|
|
400
455
|
width={dimensions().width}
|
|
401
456
|
height={dimensions().height}
|
|
402
457
|
keyboardEvent={startupKeyboardEvent()}
|
|
@@ -411,13 +466,15 @@ export async function runOpenTuiShell({
|
|
|
411
466
|
agent,
|
|
412
467
|
packageJson,
|
|
413
468
|
runtime = null,
|
|
469
|
+
preflight = null,
|
|
414
470
|
}: {
|
|
415
471
|
agent: unknown;
|
|
416
472
|
packageJson: Record<string, unknown>;
|
|
417
473
|
runtime?: any;
|
|
474
|
+
preflight?: any;
|
|
418
475
|
}) {
|
|
419
476
|
await new Promise<void>((resolve, reject) => {
|
|
420
|
-
render(() => <App agent={agent} packageJson={packageJson} runtime={runtime} />, {
|
|
477
|
+
render(() => <App agent={agent} packageJson={packageJson} runtime={runtime} preflight={preflight} />, {
|
|
421
478
|
exitOnCtrlC: false,
|
|
422
479
|
useMouse: true,
|
|
423
480
|
targetFps: 30,
|
package/wiki-workspace
CHANGED
|
@@ -773,23 +773,26 @@ cacert_compose_args() {
|
|
|
773
773
|
|
|
774
774
|
mkdir -p "$MANAGER_RUNTIME_DIR"
|
|
775
775
|
local override_path="$MANAGER_RUNTIME_DIR/$override_name"
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
776
|
+
local tmp_override="$override_path.tmp.$$"
|
|
777
|
+
{
|
|
778
|
+
printf '# Generated by wiki-manager. Changes are overwritten on the next compose command.\n'
|
|
779
|
+
printf 'services:\n'
|
|
780
|
+
while IFS= read -r service || [[ -n "$service" ]]; do
|
|
781
|
+
[[ -n "$service" ]] || continue
|
|
782
|
+
printf ' %s:\n' "$service"
|
|
783
|
+
printf ' volumes:\n'
|
|
784
|
+
printf ' - %s:/wiki-manager-ca.pem:ro\n' "$CACERT_PATH"
|
|
785
|
+
printf ' environment:\n'
|
|
786
|
+
printf ' NODE_EXTRA_CA_CERTS: /wiki-manager-ca.pem\n'
|
|
787
|
+
printf ' SSL_CERT_FILE: /wiki-manager-ca.pem\n'
|
|
788
|
+
printf ' REQUESTS_CA_BUNDLE: /wiki-manager-ca.pem\n'
|
|
789
|
+
printf ' CURL_CA_BUNDLE: /wiki-manager-ca.pem\n'
|
|
790
|
+
done <<< "$services"
|
|
791
|
+
} > "$tmp_override"
|
|
792
|
+
# Always replace generated state: package updates may add/remove services,
|
|
793
|
+
# and retaining an older override creates invalid phantom services (for
|
|
794
|
+
# example a removed optional mailer with no image in the current base file).
|
|
795
|
+
mv "$tmp_override" "$override_path"
|
|
793
796
|
printf '%s\n' -f "$override_path"
|
|
794
797
|
}
|
|
795
798
|
|