@dotdrelle/wiki-manager 0.15.48 → 0.15.49
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dotdrelle/wiki-manager",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.49",
|
|
4
4
|
"description": "Agentic shell and orchestration cockpit for llm-wiki workspaces.",
|
|
5
5
|
"license": "PolyForm-Noncommercial-1.0.0",
|
|
6
6
|
"author": "dotrelle",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"start": "bun ./bin/wiki-manager.js",
|
|
14
|
-
"test": "node --test src/core/skillInvocation.test.js src/core/skillCompiler.test.js src/runtime/skillRun.test.js src/runtime/controlDrain.test.js src/runtime/controlCancellation.test.js src/cli/runtimeStartup.test.js src/cli/wiki-manager.test.js src/agent/graph.test.js src/agent/skillRecursion.test.js src/contracts/schemas.test.js src/core/activity.test.js src/core/env.test.js src/core/agentsCompose.test.js src/core/profileServiceStatus.test.js src/core/workspaceProfile.test.js src/core/buildInfo.test.js src/core/agentEvents.test.js src/core/skillChainView.test.js src/core/runtimeLog.test.js src/activity/activityAggregator.test.js src/graph/runGraphProjector.test.js src/core/workflow.test.js src/core/planPatch.test.js src/core/agentLoop.test.js src/core/plan.test.js src/core/mcp.test.js src/core/toolLoop.test.js src/core/documentIntake.test.js src/core/dockerCompose.test.js src/core/otherWorkspacesRunning.test.js src/core/wikiSetup.test.js src/core/wikiWorkspace.test.js src/core/wikirc.test.js src/core/workspaceInherit.test.js src/core/cacert.test.js src/core/composeOverrides.test.js src/core/setEnvValue.test.js src/core/commandFailure.test.js src/core/googleGrants.test.js src/core/modelFetch.test.js src/core/startupCheck.test.js src/core/queueStore.test.js src/orchestrator/agentRegistry.test.js src/orchestrator/capabilityRegistry.test.js src/orchestrator/capabilityResolver.test.js src/orchestrator/planValidator.test.js src/orchestrator/planIntegrator.test.js src/orchestrator/taskStatuses.test.js src/orchestrator/scheduler.test.js src/orchestrator/attemptManager.test.js src/orchestrator/resultAggregator.test.js src/orchestrator/approvalPolicy.test.js src/orchestrator/dispatcher.test.js src/orchestrator/objectiveResolver.test.js src/commands/slash.test.js src/shell/repl.test.js src/shell/setupWizardModality.test.js src/shell/setupWizardPlaceholders.test.js src/shell/setupWizardSuggestions.test.js src/shell/setupWizardDiscovery.test.js src/shell/wrapText.test.js src/runtime/lifecycle.test.js src/runtime/store.test.js src/runtime/workspaceIsolation.test.js src/runtime/controlMessages.test.js src/runtime/recoveryManager.test.js src/runtime/server.test.js src/runtime/supervisor.test.js src/runtime/delegation.test.js src/runtime/runner.test.js src/runtime/runner.e2e.test.js src/runtime/skillChain.e2e.test.js src/runtime/donna-contract.test.js src/runtime/auth.test.js",
|
|
14
|
+
"test": "node --test src/core/skillInvocation.test.js src/core/skillCompiler.test.js src/runtime/skillRun.test.js src/runtime/controlDrain.test.js src/runtime/controlCancellation.test.js src/cli/runtimeStartup.test.js src/cli/wiki-manager.test.js src/agent/graph.test.js src/agent/skillRecursion.test.js src/contracts/schemas.test.js src/core/activity.test.js src/core/env.test.js src/core/agentsCompose.test.js src/core/profileServiceStatus.test.js src/core/workspaceProfile.test.js src/core/buildInfo.test.js src/core/agentEvents.test.js src/core/skillChainView.test.js src/core/runtimeLog.test.js src/activity/activityAggregator.test.js src/graph/runGraphProjector.test.js src/core/workflow.test.js src/core/planPatch.test.js src/core/agentLoop.test.js src/core/plan.test.js src/core/mcp.test.js src/core/toolLoop.test.js src/core/documentIntake.test.js src/core/dockerCompose.test.js src/core/otherWorkspacesRunning.test.js src/core/wikiSetup.test.js src/core/wikiWorkspace.test.js src/core/wikirc.test.js src/core/workspaceInherit.test.js src/core/cacert.test.js src/core/composeOverrides.test.js src/core/setEnvValue.test.js src/core/commandFailure.test.js src/core/googleGrants.test.js src/core/modelFetch.test.js src/core/startupCheck.test.js src/core/queueStore.test.js src/orchestrator/agentRegistry.test.js src/orchestrator/capabilityRegistry.test.js src/orchestrator/capabilityResolver.test.js src/orchestrator/planValidator.test.js src/orchestrator/planIntegrator.test.js src/orchestrator/taskStatuses.test.js src/orchestrator/scheduler.test.js src/orchestrator/attemptManager.test.js src/orchestrator/resultAggregator.test.js src/orchestrator/approvalPolicy.test.js src/orchestrator/dispatcher.test.js src/orchestrator/objectiveResolver.test.js src/commands/slash.test.js src/shell/repl.test.js src/shell/setupWizardModality.test.js src/shell/setupWizardPlaceholders.test.js src/shell/setupWizardSuggestions.test.js src/shell/setupWizardDiscovery.test.js src/shell/wrapText.test.js src/runtime/lifecycle.test.js src/runtime/store.test.js src/runtime/workspaceIsolation.test.js src/runtime/controlMessages.test.js src/runtime/recoveryManager.test.js src/runtime/server.test.js src/runtime/supervisor.test.js src/runtime/delegation.test.js src/runtime/runner.test.js src/runtime/runner.e2e.test.js src/runtime/skillChain.e2e.test.js src/runtime/donna-contract.test.js src/runtime/approvals.test.js src/runtime/auth.test.js",
|
|
15
15
|
"check-versions": "node scripts/check-versions.js",
|
|
16
16
|
"prepack": "node scripts/check-versions.js",
|
|
17
17
|
"prepublishOnly": "node scripts/check-versions.js",
|
package/src/core/buildInfo.json
CHANGED
package/src/core/mcp.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { managerEnvFile, managerMcpEndpointsFile, readEnvFile } from './env.js';
|
|
3
3
|
|
|
4
|
-
const WIKI_MANAGER_VERSION = '0.15.
|
|
4
|
+
const WIKI_MANAGER_VERSION = '0.15.49';
|
|
5
5
|
|
|
6
6
|
function envValue(key) {
|
|
7
7
|
const filePath = managerEnvFile();
|
package/src/runtime/approvals.js
CHANGED
|
@@ -134,11 +134,23 @@ export function createApprovalManager(session, {
|
|
|
134
134
|
function approve(request = {}) {
|
|
135
135
|
const { approvalId = null, runId = null, itemId = null } = request;
|
|
136
136
|
if (request.scope || request.planRevision != null || request.approvalClasses || request.approvalClass || request.taskId || request.groupId) {
|
|
137
|
+
const scope = normalizeGrantScope(request.scope);
|
|
138
|
+
// A run-scope grant must be bounded to a run. Without a runId it would
|
|
139
|
+
// read as a permanent, workspace-wide grant in `grantCoversTask` (its
|
|
140
|
+
// runId/revision/class checks all skip on null) — one bare `{scope:'run'}`
|
|
141
|
+
// could then unlock every mutating task of every run, forever. Fall back
|
|
142
|
+
// to the active run identity and refuse rather than mint an unbounded
|
|
143
|
+
// grant when there is none.
|
|
144
|
+
const effectiveRunId = request.runId ?? session._currentRunIdentity?.runId ?? null;
|
|
145
|
+
if (scope === 'run' && !effectiveRunId) {
|
|
146
|
+
return { approved: false, reason: 'run_scope_requires_runId' };
|
|
147
|
+
}
|
|
137
148
|
const grant = normalizeApprovalGrant({
|
|
138
149
|
...request,
|
|
139
150
|
id: request.id ?? request.approvalId ?? randomUUID(),
|
|
140
151
|
workspaceId: request.workspaceId ?? request.workspace ?? session.workspace ?? null,
|
|
141
|
-
scope
|
|
152
|
+
scope,
|
|
153
|
+
runId: effectiveRunId,
|
|
142
154
|
itemId: request.itemId ?? request.taskId ?? null,
|
|
143
155
|
status: 'approved',
|
|
144
156
|
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import test from 'node:test';
|
|
3
|
+
|
|
4
|
+
import { createApprovalManager } from './approvals.js';
|
|
5
|
+
|
|
6
|
+
test('approve() refuses an unbounded run-scope grant', () => {
|
|
7
|
+
const manager = createApprovalManager({ workspace: 'docs' });
|
|
8
|
+
const result = manager.approve({ scope: 'run' });
|
|
9
|
+
|
|
10
|
+
assert.equal(result.approved, false);
|
|
11
|
+
assert.equal(result.reason, 'run_scope_requires_runId');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test('approve() bounds a bare run-scope grant to the active run identity', () => {
|
|
15
|
+
const manager = createApprovalManager({
|
|
16
|
+
workspace: 'docs',
|
|
17
|
+
_currentRunIdentity: { runId: 'run-1', workspace: 'docs' },
|
|
18
|
+
});
|
|
19
|
+
const result = manager.approve({ scope: 'run' });
|
|
20
|
+
|
|
21
|
+
assert.equal(result.approved, true);
|
|
22
|
+
assert.equal(result.runId, 'run-1');
|
|
23
|
+
assert.equal(result.scope, 'run');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('approve() keeps an explicit runId even without a live run identity', () => {
|
|
27
|
+
const manager = createApprovalManager({ workspace: 'docs' });
|
|
28
|
+
const result = manager.approve({ scope: 'run', runId: 'run-2' });
|
|
29
|
+
|
|
30
|
+
assert.equal(result.approved, true);
|
|
31
|
+
assert.equal(result.runId, 'run-2');
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
test('approve() leaves task/tool/group grants unblocked by the run guard', () => {
|
|
35
|
+
const manager = createApprovalManager({ workspace: 'docs' });
|
|
36
|
+
|
|
37
|
+
const task = manager.approve({ scope: 'task', taskId: 'run-1:build' });
|
|
38
|
+
assert.equal(task.approved, true);
|
|
39
|
+
assert.equal(task.scope, 'task');
|
|
40
|
+
|
|
41
|
+
const group = manager.approve({ scope: 'group', groupId: 'publish' });
|
|
42
|
+
assert.equal(group.approved, true);
|
|
43
|
+
assert.equal(group.scope, 'group');
|
|
44
|
+
});
|
package/src/runtime/server.js
CHANGED
|
@@ -541,6 +541,13 @@ export function startRuntimeServer({
|
|
|
541
541
|
const runId = url.searchParams.get('runId') ?? body.runId ?? null;
|
|
542
542
|
const purge = body.purge === true || url.searchParams.get('purge') === 'true';
|
|
543
543
|
const context = await resolveContext({ workspace });
|
|
544
|
+
const resolvedWorkspace = context?.workspace ?? workspace ?? null;
|
|
545
|
+
if (purge && !runId && !resolvedWorkspace) {
|
|
546
|
+
// Purge is workspace-wide and destructive: without a scope it would
|
|
547
|
+
// wipe every workspace's history. Mirror /conversation/truncate.
|
|
548
|
+
sendJson(response, 400, { killed: false, reason: 'workspace_required' });
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
544
551
|
const result = await killRuntimeRuns(context, { workspace, runId, purge });
|
|
545
552
|
publishState(context.workspace ?? workspace ?? null, context);
|
|
546
553
|
sendJson(response, 202, result);
|
|
@@ -728,6 +728,57 @@ test('runtime server kill can target a specific run id', async (t) => {
|
|
|
728
728
|
}
|
|
729
729
|
});
|
|
730
730
|
|
|
731
|
+
test('runtime server kill purge without workspace is refused', async (t) => {
|
|
732
|
+
let clearedArgs = null;
|
|
733
|
+
let handle;
|
|
734
|
+
try {
|
|
735
|
+
handle = await startRuntimeServer({
|
|
736
|
+
host: '127.0.0.1',
|
|
737
|
+
port: 0,
|
|
738
|
+
store: {
|
|
739
|
+
dbPath: ':memory:',
|
|
740
|
+
getState: () => ({ status: 'idle' }),
|
|
741
|
+
listEvents: () => [],
|
|
742
|
+
interruptRuns: () => 0,
|
|
743
|
+
cancelActiveTasksForInterruptedRuns: () => 0,
|
|
744
|
+
clearWorkspaceState: (args) => {
|
|
745
|
+
clearedArgs = args;
|
|
746
|
+
return { runs: 0, events: 0, queue: 0 };
|
|
747
|
+
},
|
|
748
|
+
},
|
|
749
|
+
session: {},
|
|
750
|
+
run: async () => {},
|
|
751
|
+
});
|
|
752
|
+
} catch (err) {
|
|
753
|
+
if (err?.code === 'EPERM') {
|
|
754
|
+
t.skip('network listen is not permitted in this sandbox');
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
throw err;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
try {
|
|
761
|
+
const unscoped = await fetch(`http://127.0.0.1:${handle.port}/kill`, {
|
|
762
|
+
method: 'POST',
|
|
763
|
+
headers: { 'Content-Type': 'application/json' },
|
|
764
|
+
body: JSON.stringify({ purge: true }),
|
|
765
|
+
});
|
|
766
|
+
assert.equal(unscoped.status, 400);
|
|
767
|
+
assert.deepEqual(await unscoped.json(), { killed: false, reason: 'workspace_required' });
|
|
768
|
+
assert.equal(clearedArgs, null);
|
|
769
|
+
|
|
770
|
+
const scoped = await fetch(`http://127.0.0.1:${handle.port}/kill?workspace=docs`, {
|
|
771
|
+
method: 'POST',
|
|
772
|
+
headers: { 'Content-Type': 'application/json' },
|
|
773
|
+
body: JSON.stringify({ purge: true }),
|
|
774
|
+
});
|
|
775
|
+
assert.equal(scoped.status, 202);
|
|
776
|
+
assert.equal(clearedArgs.workspace, 'docs');
|
|
777
|
+
} finally {
|
|
778
|
+
await handle.close();
|
|
779
|
+
}
|
|
780
|
+
});
|
|
781
|
+
|
|
731
782
|
test('runtime server state exposes active run identity while running', async (t) => {
|
|
732
783
|
let releaseRun;
|
|
733
784
|
const context = {
|