@thehammer/danx-dashboard-mcp 0.1.301 → 0.1.303
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/dist/http-client.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { boardStampOf } from "./route-board-scope.js";
|
|
2
2
|
import { assertVersionFloorSatisfied, MCP_MIN_VERSION_HEADER } from "./version-floor.js";
|
|
3
|
+
import { PLUGIN_BACKGROUND_HEADER } from "./session-options.js";
|
|
3
4
|
export class DashboardHttpClient {
|
|
4
5
|
config;
|
|
5
6
|
fetchImpl;
|
|
@@ -17,6 +18,14 @@ export class DashboardHttpClient {
|
|
|
17
18
|
setToken(token) {
|
|
18
19
|
this.config.token = token;
|
|
19
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* DX-5076 - the ONE entry for a request this process makes on its own (the listener's health read, the key-permission read, the permission claim
|
|
23
|
+
* poll): it is never the agent acting, so it carries the background mark and ends no agent pause. A call the agent makes (`danxbot_api`, a
|
|
24
|
+
* permission-request create) goes through `request` instead. No call site sets `background` by hand.
|
|
25
|
+
*/
|
|
26
|
+
requestOwn(args) {
|
|
27
|
+
return this.request({ ...args, background: true });
|
|
28
|
+
}
|
|
20
29
|
async request(args) {
|
|
21
30
|
if (this.config.token === "") {
|
|
22
31
|
// DX-4390 — a caller reaches here only past the sign-in halt; a bearer-less call is a bug.
|
|
@@ -51,7 +60,7 @@ export class DashboardHttpClient {
|
|
|
51
60
|
headers["x-danx-session-id"] = this.config.session.id;
|
|
52
61
|
}
|
|
53
62
|
if (args.background === true) {
|
|
54
|
-
headers[
|
|
63
|
+
headers[PLUGIN_BACKGROUND_HEADER] = "1";
|
|
55
64
|
}
|
|
56
65
|
let bodyString;
|
|
57
66
|
if (args.body !== undefined) {
|
package/dist/index.js
CHANGED
|
@@ -217,11 +217,12 @@ function boot() {
|
|
|
217
217
|
permissionRequests = new PermissionRequests({
|
|
218
218
|
access,
|
|
219
219
|
request: (args) => dashboardClient.request(args),
|
|
220
|
+
requestOwn: (args) => dashboardClient.requestOwn(args),
|
|
220
221
|
log: (line) => console.error(line),
|
|
221
222
|
});
|
|
222
223
|
listenerReminder = createListenerReminder({
|
|
223
224
|
sessionId: config.session?.id,
|
|
224
|
-
fetchHealth: () => dashboardClient.
|
|
225
|
+
fetchHealth: () => dashboardClient.requestOwn({ method: "GET", basePath: "", path: "/api/plans", query: { limit: 1 } }),
|
|
225
226
|
isPlanConnected: isPlanConnectedOnThisMachine,
|
|
226
227
|
now: Date.now,
|
|
227
228
|
logLine: (line) => console.error(line),
|
|
@@ -270,7 +271,8 @@ function boot() {
|
|
|
270
271
|
async function readKeyPermissions() {
|
|
271
272
|
if (!access.isSignedIn())
|
|
272
273
|
return { outcome: "no-key" };
|
|
273
|
-
|
|
274
|
+
// DX-5076: this process reading its own key's permissions is not the agent acting.
|
|
275
|
+
const guarded = await access.guard(() => client.requestOwn({ method: "GET", basePath: "", path: "/api/auth/me" }));
|
|
274
276
|
if ("halt" in guarded)
|
|
275
277
|
return { outcome: "no-key" };
|
|
276
278
|
const { result } = guarded;
|
|
@@ -96,7 +96,7 @@ export class PermissionRequests {
|
|
|
96
96
|
let guarded;
|
|
97
97
|
try {
|
|
98
98
|
// `guard` runs before EVERY claim (DX-4418): a revoked or signed-out session answers its halt without a request.
|
|
99
|
-
guarded = await this.deps.access.guard(() => this.deps.
|
|
99
|
+
guarded = await this.deps.access.guard(() => this.deps.requestOwn({ method: "POST", basePath: PERMISSION_REQUESTS_BASE_PATH, path: `/${request.publicId}/claim` }));
|
|
100
100
|
}
|
|
101
101
|
catch (err) {
|
|
102
102
|
// An outdated MCP will never get a different answer; any other failure is retried until the request ends.
|
|
@@ -40,6 +40,7 @@ export const GET_ROUTE_BOARD_SCOPE = [
|
|
|
40
40
|
["/api/platform/teams", "refuse"],
|
|
41
41
|
["/api/reminders", "refuse"],
|
|
42
42
|
["/api/repos", "refuse"],
|
|
43
|
+
["/api/security-incidents", "refuse"],
|
|
43
44
|
["/api/self-repair/errors", "refuse"],
|
|
44
45
|
["/api/sync-root", "refuse"],
|
|
45
46
|
["/api/tasks", "refuse"],
|
package/dist/session-options.js
CHANGED
|
@@ -10,6 +10,8 @@ import { credentialFingerprint, describeCredentialSource, readCredential } from
|
|
|
10
10
|
import { readSessionConnection } from "./session-connection.js";
|
|
11
11
|
import { fixForStop } from "./stop-fixes.js";
|
|
12
12
|
export const SESSION_ID_HEADER = "x-danx-session-id";
|
|
13
|
+
/** DX-5033 / DX-5076 - marks a request as this process's own background work (not the agent acting): the dashboard ends no agent pause on it. */
|
|
14
|
+
export const PLUGIN_BACKGROUND_HEADER = "x-danx-plugin-background";
|
|
13
15
|
/** A start this process cannot make, named the way the session will be told about it. */
|
|
14
16
|
export class SessionStartError extends Error {
|
|
15
17
|
// `ListenStopReason`, not `string`: a start-time failure is always one of `no_connection_record` / `credential_unavailable`
|
package/dist/session-stream.js
CHANGED
|
@@ -10,7 +10,7 @@ import { errorCodeOf } from "./json-body.js";
|
|
|
10
10
|
import { boundRequest } from "./request-bound.js";
|
|
11
11
|
import { keyRevocationOf, keyRevokedHalt } from "./key-revoked-halt.js";
|
|
12
12
|
import { oneLine } from "./one-line.js";
|
|
13
|
-
import { SESSION_ID_HEADER } from "./session-options.js";
|
|
13
|
+
import { PLUGIN_BACKGROUND_HEADER, SESSION_ID_HEADER } from "./session-options.js";
|
|
14
14
|
import { isClaimState } from "@thehammer/danx-session-telemetry";
|
|
15
15
|
/**
|
|
16
16
|
* DX-3912 — the longest heartbeat `reason` the relay sends: one under the dashboard's own
|
|
@@ -74,6 +74,8 @@ async function request(options, deps, what, url, init = { method: "GET" }) {
|
|
|
74
74
|
Authorization: `Bearer ${options.token}`,
|
|
75
75
|
Accept: "application/json",
|
|
76
76
|
[SESSION_ID_HEADER]: options.sessionId,
|
|
77
|
+
// DX-5076: every request this module makes is the relay's own work (ticket mint, inventory read, heartbeat), never the agent acting, so it must not end an agent pause. One marking point, so a new request here cannot forget it.
|
|
78
|
+
[PLUGIN_BACKGROUND_HEADER]: "1",
|
|
77
79
|
};
|
|
78
80
|
if (init.body !== undefined)
|
|
79
81
|
headers["Content-Type"] = "application/json";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thehammer/danx-dashboard-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.303",
|
|
4
4
|
"description": "Stdio MCP server fronting danxbot's dashboard API for agents (operator sessions and dispatched workers alike): the generic danxbot_api/danxbot_api_list/danxbot_api_spec tools reach any route the caller's credential may call, plus dedicated agent-specific tools (plan_connect, request_permission, attach_file, and danxbot_slack_reply) (DX-3465, PLN-11 R-25).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|