@adhdev/mesh-shared 1.0.82-rc.23 → 1.0.82-rc.24
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/assistant-protocol.d.ts +119 -2
- package/dist/index.js +79 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +70 -2
- package/dist/index.mjs.map +1 -1
- package/dist/mesh-tool-names.d.ts +2 -2
- package/dist/protocol/dashboard-daemon-p2p.d.ts +1 -1
- package/dist/worker-protocol.d.ts +1 -1
- package/package.json +1 -1
- package/src/assistant-protocol.ts +208 -2
- package/src/mesh-tool-names.ts +1 -0
- package/src/worker-protocol.ts +1 -0
|
@@ -62,11 +62,128 @@ export declare const ASSISTANT_WRITE_TOOLS: readonly AssistantTool[];
|
|
|
62
62
|
export declare const ASSISTANT_OWNER_VERBS: readonly AssistantVerb[];
|
|
63
63
|
/** The only assistant verbs accepted while an idle review turn is open (§4.10.7). */
|
|
64
64
|
export declare const ASSISTANT_REVIEW_TURN_VERBS: readonly AssistantVerb[];
|
|
65
|
-
/**
|
|
66
|
-
* Env var the daemon sets on the assistant CLI's process (§4.5), read by the
|
|
65
|
+
/** Env var the daemon sets on the assistant CLI's process (§4.5), read by the
|
|
67
66
|
* assistant MCP server and forwarded on every verb as
|
|
68
67
|
* `ASSISTANT_SESSION_ID_ARG`. Routing / ownership only — never an auth gate.
|
|
69
68
|
*/
|
|
70
69
|
export declare const ASSISTANT_SESSION_ID_ENV = "ADHDEV_ASSISTANT_SESSION_ID";
|
|
71
70
|
/** Request arg carrying the calling assistant session id. */
|
|
72
71
|
export declare const ASSISTANT_SESSION_ID_ARG = "assistantSessionId";
|
|
72
|
+
/**
|
|
73
|
+
* Conceptual single-assistant slot in the verified account namespace.
|
|
74
|
+
* Fixed to `'personal'` — one logical assistant per account with one
|
|
75
|
+
* owner-selected active execution daemon binding per project ACL.
|
|
76
|
+
*/
|
|
77
|
+
export declare const ASSISTANT_ACCOUNT_SLOT: "personal";
|
|
78
|
+
export type AssistantAccountSlot = typeof ASSISTANT_ACCOUNT_SLOT;
|
|
79
|
+
/**
|
|
80
|
+
* Daemon commands for remote project discovery, host ACL grant/revoke, and
|
|
81
|
+
* assistant-side follow/unfollow. Registered outside `ASSISTANT_VERB` so the
|
|
82
|
+
* assistant MCP server tool/verb parity table remains untouched.
|
|
83
|
+
*/
|
|
84
|
+
export declare const ASSISTANT_REMOTE_PROJECT_COMMAND: "assistant_remote_project";
|
|
85
|
+
export declare const ASSISTANT_REMOTE_PROJECT_CATALOG_COMMAND: "assistant_remote_project_catalog";
|
|
86
|
+
export declare const ASSISTANT_REMOTE_PROJECT_ACCESS_COMMAND: "assistant_remote_project_access";
|
|
87
|
+
export declare const ASSISTANT_REMOTE_FOLLOW_COMMAND: "assistant_remote_follow";
|
|
88
|
+
/**
|
|
89
|
+
* Narrow operations a non-roster follower deputy is permitted to invoke on
|
|
90
|
+
* `assistant_remote_project` when the host's `assistantRemoteAccess` ACL is active.
|
|
91
|
+
* `note`, `terminal`, and `inventory` remain strictly roster-member-only.
|
|
92
|
+
*/
|
|
93
|
+
export declare const ASSISTANT_FOLLOWER_ALLOWED_OPS: readonly ["status", "read", "poll", "report", "send"];
|
|
94
|
+
export type AssistantFollowerAllowedOp = typeof ASSISTANT_FOLLOWER_ALLOWED_OPS[number];
|
|
95
|
+
export declare function isAssistantFollowerAllowedOp(value: unknown): value is AssistantFollowerAllowedOp;
|
|
96
|
+
/**
|
|
97
|
+
* Host-authoritative narrow project ACL persisted on the hosting daemon's
|
|
98
|
+
* `LocalMeshEntry` in `meshes.json`. Revocation increments `grantRevision`
|
|
99
|
+
* and retains a `'revoked'` tombstone so stale follower caches cannot replay.
|
|
100
|
+
*/
|
|
101
|
+
export interface AssistantRemoteAccessBinding {
|
|
102
|
+
hostDaemonId: string;
|
|
103
|
+
meshId: string;
|
|
104
|
+
accountSlot: AssistantAccountSlot;
|
|
105
|
+
activeDaemonId: string;
|
|
106
|
+
bindingRevision: number;
|
|
107
|
+
grantRevision: number;
|
|
108
|
+
status: 'active' | 'revoked';
|
|
109
|
+
allowedOps: readonly AssistantFollowerAllowedOp[];
|
|
110
|
+
grantedAt: number;
|
|
111
|
+
revokedAt?: number;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Durable owner-binding receipt persisted in the assistant daemon's
|
|
115
|
+
* `assistant.json`. Survives ordinary daemon restarts and session/provider
|
|
116
|
+
* replacements (`bindSession`), while missing/corrupt/mismatched receipts
|
|
117
|
+
* fail closed until owner reconciliation.
|
|
118
|
+
*/
|
|
119
|
+
export interface AssistantOwnerBindingReceipt {
|
|
120
|
+
accountSlot: AssistantAccountSlot;
|
|
121
|
+
daemonId: string;
|
|
122
|
+
bindingRevision: number;
|
|
123
|
+
boundAt: number | string;
|
|
124
|
+
}
|
|
125
|
+
export type FollowedRemoteProjectState = 'followed' | 'unfollowed' | 'revoked';
|
|
126
|
+
export type RemoteAccessState = 'not_granted' | 'granted_unfollowed' | 'followed' | 'revoked' | 'host_unreachable' | 'binding_mismatch';
|
|
127
|
+
/**
|
|
128
|
+
* Assistant-local followed remote project reference persisted in `assistant.json`.
|
|
129
|
+
* Never injected into `meshes.json`, `mesh-host-records.json`, `mesh-node-state-push.json`,
|
|
130
|
+
* or `inlineMeshCache`.
|
|
131
|
+
*/
|
|
132
|
+
export interface FollowedRemoteProjectEntry {
|
|
133
|
+
/** Canonical key: `${canonicalDaemonId(hostDaemonId)}::${meshId}` */
|
|
134
|
+
key: string;
|
|
135
|
+
hostDaemonId: string;
|
|
136
|
+
hostLabel?: string;
|
|
137
|
+
meshId: string;
|
|
138
|
+
name: string;
|
|
139
|
+
slug: string;
|
|
140
|
+
sanitizedRepoIdentity: string | null;
|
|
141
|
+
repoIdentity?: string;
|
|
142
|
+
accountSlot: AssistantAccountSlot;
|
|
143
|
+
bindingRevision: number;
|
|
144
|
+
grantRevision: number;
|
|
145
|
+
state: FollowedRemoteProjectState;
|
|
146
|
+
followedAt: number | string;
|
|
147
|
+
updatedAt: number | string;
|
|
148
|
+
unfollowedAt?: number | string;
|
|
149
|
+
revokedAt?: number | string;
|
|
150
|
+
lastCursor?: string | null;
|
|
151
|
+
coordinatorSessionId?: string | null;
|
|
152
|
+
lastErrorCode?: string;
|
|
153
|
+
lastObserved?: {
|
|
154
|
+
observedAt: number | string;
|
|
155
|
+
coordinatorState?: string;
|
|
156
|
+
coordinatorMissing?: boolean;
|
|
157
|
+
coordinatorPresent?: boolean;
|
|
158
|
+
lastHeadline?: string;
|
|
159
|
+
summary?: string;
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Content-free canonical catalog metadata returned by `assistant_remote_project_catalog`
|
|
164
|
+
* for meshes actually hosted on the queried remote daemon.
|
|
165
|
+
*/
|
|
166
|
+
export interface RemoteProjectCatalogItem {
|
|
167
|
+
hostDaemonId: string;
|
|
168
|
+
meshId: string;
|
|
169
|
+
name: string;
|
|
170
|
+
sanitizedRepoIdentity: string | null;
|
|
171
|
+
coordinatorState?: 'none' | 'idle' | 'working' | 'waiting' | string;
|
|
172
|
+
capabilities: {
|
|
173
|
+
status: true;
|
|
174
|
+
read: true;
|
|
175
|
+
poll: true;
|
|
176
|
+
report: true;
|
|
177
|
+
send: true;
|
|
178
|
+
coordinatorPresent?: boolean;
|
|
179
|
+
};
|
|
180
|
+
observedAt: number | string;
|
|
181
|
+
}
|
|
182
|
+
/** Build the canonical `(hostDaemonId, meshId)` key used across assistant follow state. */
|
|
183
|
+
export declare function followedRemoteProjectKey(hostDaemonId: string, meshId: string): string;
|
|
184
|
+
/**
|
|
185
|
+
* Sanitize a repository identity or remote URL into a content-free `host/path`
|
|
186
|
+
* identifier suitable for remote discovery catalogs. Strips credentials, query
|
|
187
|
+
* strings, fragments, and `.git` suffixes, and rejects local filesystem paths.
|
|
188
|
+
*/
|
|
189
|
+
export declare function sanitizeRemoteRepoIdentity(raw: string | null | undefined): string | null;
|
package/dist/index.js
CHANGED
|
@@ -20,7 +20,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
ASSISTANT_ACCOUNT_SLOT: () => ASSISTANT_ACCOUNT_SLOT,
|
|
24
|
+
ASSISTANT_FOLLOWER_ALLOWED_OPS: () => ASSISTANT_FOLLOWER_ALLOWED_OPS,
|
|
23
25
|
ASSISTANT_OWNER_VERBS: () => ASSISTANT_OWNER_VERBS,
|
|
26
|
+
ASSISTANT_REMOTE_FOLLOW_COMMAND: () => ASSISTANT_REMOTE_FOLLOW_COMMAND,
|
|
27
|
+
ASSISTANT_REMOTE_PROJECT_ACCESS_COMMAND: () => ASSISTANT_REMOTE_PROJECT_ACCESS_COMMAND,
|
|
28
|
+
ASSISTANT_REMOTE_PROJECT_CATALOG_COMMAND: () => ASSISTANT_REMOTE_PROJECT_CATALOG_COMMAND,
|
|
29
|
+
ASSISTANT_REMOTE_PROJECT_COMMAND: () => ASSISTANT_REMOTE_PROJECT_COMMAND,
|
|
24
30
|
ASSISTANT_REVIEW_TURN_VERBS: () => ASSISTANT_REVIEW_TURN_VERBS,
|
|
25
31
|
ASSISTANT_SESSION_ID_ARG: () => ASSISTANT_SESSION_ID_ARG,
|
|
26
32
|
ASSISTANT_SESSION_ID_ENV: () => ASSISTANT_SESSION_ID_ENV,
|
|
@@ -229,11 +235,13 @@ __export(index_exports, {
|
|
|
229
235
|
expandDaemonIdForms: () => expandDaemonIdForms,
|
|
230
236
|
findOwnershipConflicts: () => findOwnershipConflicts,
|
|
231
237
|
foldKeyedDoc: () => foldKeyedDoc,
|
|
238
|
+
followedRemoteProjectKey: () => followedRemoteProjectKey,
|
|
232
239
|
formatQuotaAccount: () => formatQuotaAccount,
|
|
233
240
|
hasGitStatusEvidence: () => hasGitStatusEvidence,
|
|
234
241
|
hasWorkerProtocolFooter: () => hasWorkerProtocolFooter,
|
|
235
242
|
interpolateString: () => interpolateString,
|
|
236
243
|
isActionableProviderApproval: () => isActionableProviderApproval,
|
|
244
|
+
isAssistantFollowerAllowedOp: () => isAssistantFollowerAllowedOp,
|
|
237
245
|
isAssistantTool: () => isAssistantTool,
|
|
238
246
|
isBlockedStatus: () => isBlockedStatus,
|
|
239
247
|
isBusyStatus: () => isBusyStatus,
|
|
@@ -357,6 +365,7 @@ __export(index_exports, {
|
|
|
357
365
|
retiredMeshToolError: () => retiredMeshToolError,
|
|
358
366
|
sanitizeModelIdentifier: () => sanitizeModelIdentifier,
|
|
359
367
|
sanitizeRefusalCode: () => sanitizeRefusalCode,
|
|
368
|
+
sanitizeRemoteRepoIdentity: () => sanitizeRemoteRepoIdentity,
|
|
360
369
|
scoreGitStatusCandidate: () => scoreGitStatusCandidate,
|
|
361
370
|
scoreGitUpstreamFreshness: () => scoreGitUpstreamFreshness,
|
|
362
371
|
sessionIdsEquivalent: () => sessionIdsEquivalent,
|
|
@@ -1164,7 +1173,8 @@ var CANONICAL_MESH_TOOL_NAMES = [
|
|
|
1164
1173
|
"mesh_review_inbox",
|
|
1165
1174
|
"mesh_node_slots",
|
|
1166
1175
|
"driver_list",
|
|
1167
|
-
"driver_describe"
|
|
1176
|
+
"driver_describe",
|
|
1177
|
+
"artifact_list"
|
|
1168
1178
|
];
|
|
1169
1179
|
var CANONICAL_MESH_TOOL_COUNT = CANONICAL_MESH_TOOL_NAMES.length;
|
|
1170
1180
|
var RETIRED_MESH_TOOLS = {
|
|
@@ -2048,7 +2058,8 @@ var WORKER_TOOLS = [
|
|
|
2048
2058
|
"git_diff",
|
|
2049
2059
|
"driver_list",
|
|
2050
2060
|
"driver_describe",
|
|
2051
|
-
"driver_invoke"
|
|
2061
|
+
"driver_invoke",
|
|
2062
|
+
"artifact_register"
|
|
2052
2063
|
];
|
|
2053
2064
|
var WORKER_TOOL_SET = new Set(WORKER_TOOLS);
|
|
2054
2065
|
function isWorkerTool(value) {
|
|
@@ -2224,6 +2235,63 @@ var ASSISTANT_REVIEW_TURN_VERBS = [
|
|
|
2224
2235
|
];
|
|
2225
2236
|
var ASSISTANT_SESSION_ID_ENV = "ADHDEV_ASSISTANT_SESSION_ID";
|
|
2226
2237
|
var ASSISTANT_SESSION_ID_ARG = "assistantSessionId";
|
|
2238
|
+
var ASSISTANT_ACCOUNT_SLOT = "personal";
|
|
2239
|
+
var ASSISTANT_REMOTE_PROJECT_COMMAND = "assistant_remote_project";
|
|
2240
|
+
var ASSISTANT_REMOTE_PROJECT_CATALOG_COMMAND = "assistant_remote_project_catalog";
|
|
2241
|
+
var ASSISTANT_REMOTE_PROJECT_ACCESS_COMMAND = "assistant_remote_project_access";
|
|
2242
|
+
var ASSISTANT_REMOTE_FOLLOW_COMMAND = "assistant_remote_follow";
|
|
2243
|
+
var ASSISTANT_FOLLOWER_ALLOWED_OPS = ["status", "read", "poll", "report", "send"];
|
|
2244
|
+
var ASSISTANT_FOLLOWER_ALLOWED_OP_SET = new Set(ASSISTANT_FOLLOWER_ALLOWED_OPS);
|
|
2245
|
+
function isAssistantFollowerAllowedOp(value) {
|
|
2246
|
+
return typeof value === "string" && ASSISTANT_FOLLOWER_ALLOWED_OP_SET.has(value);
|
|
2247
|
+
}
|
|
2248
|
+
function followedRemoteProjectKey(hostDaemonId, meshId) {
|
|
2249
|
+
const canonHost = canonicalDaemonId(hostDaemonId) ?? hostDaemonId.trim();
|
|
2250
|
+
return `${canonHost}::${meshId.trim()}`;
|
|
2251
|
+
}
|
|
2252
|
+
function sanitizeRemoteRepoIdentity(raw) {
|
|
2253
|
+
if (typeof raw !== "string") return null;
|
|
2254
|
+
const trimmed = raw.trim();
|
|
2255
|
+
if (!trimmed) return null;
|
|
2256
|
+
if (trimmed.startsWith("/") || trimmed.startsWith("./") || trimmed.startsWith("../") || trimmed.startsWith("~/") || trimmed.startsWith("\\") || /^[a-zA-Z]:[\\/]/.test(trimmed) || /^file:/i.test(trimmed)) {
|
|
2257
|
+
return null;
|
|
2258
|
+
}
|
|
2259
|
+
const withoutQuery = trimmed.replace(/[?#].*$/, "").replace(/\/+$/, "");
|
|
2260
|
+
if (!withoutQuery) return null;
|
|
2261
|
+
let host = "";
|
|
2262
|
+
let repoPath = "";
|
|
2263
|
+
if (/^[a-z][a-z0-9+.-]*:\/\//i.test(withoutQuery)) {
|
|
2264
|
+
try {
|
|
2265
|
+
const url = new URL(withoutQuery);
|
|
2266
|
+
if (url.protocol === "file:") return null;
|
|
2267
|
+
host = url.hostname.toLowerCase();
|
|
2268
|
+
repoPath = decodeURIComponent(url.pathname).replace(/^\/+|\/+$/g, "").replace(/\.git$/i, "");
|
|
2269
|
+
} catch {
|
|
2270
|
+
return null;
|
|
2271
|
+
}
|
|
2272
|
+
} else {
|
|
2273
|
+
const scpMatch = withoutQuery.match(/^(?:[^@/:]+@)?(\[[^\]]+\]|[^/:]+):(.+)$/);
|
|
2274
|
+
if (scpMatch) {
|
|
2275
|
+
host = scpMatch[1].replace(/^\[|\]$/g, "").toLowerCase();
|
|
2276
|
+
repoPath = scpMatch[2].replace(/^\/+|\/+$/g, "").replace(/\.git$/i, "");
|
|
2277
|
+
} else {
|
|
2278
|
+
const slash = withoutQuery.indexOf("/");
|
|
2279
|
+
if (slash > 0) {
|
|
2280
|
+
const rawHost = withoutQuery.slice(0, slash);
|
|
2281
|
+
const atIdx = rawHost.lastIndexOf("@");
|
|
2282
|
+
host = (atIdx >= 0 ? rawHost.slice(atIdx + 1) : rawHost).toLowerCase();
|
|
2283
|
+
repoPath = withoutQuery.slice(slash + 1).replace(/^\/+|\/+$/g, "").replace(/\.git$/i, "");
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
if (!host || !repoPath) return null;
|
|
2288
|
+
if (!host.includes(".") && host !== "localhost") return null;
|
|
2289
|
+
if (/[\s@:\\]/.test(host)) return null;
|
|
2290
|
+
const segments = repoPath.split("/").filter(Boolean);
|
|
2291
|
+
if (segments.length === 0) return null;
|
|
2292
|
+
if (segments.some((seg) => seg === "." || seg === ".." || /[\s@:\\]/.test(seg))) return null;
|
|
2293
|
+
return `${host}/${segments.join("/")}`.slice(0, 200);
|
|
2294
|
+
}
|
|
2227
2295
|
|
|
2228
2296
|
// src/turn-evidence.ts
|
|
2229
2297
|
var MESH_TOPIC_PROTOCOL_VERSION = 2;
|
|
@@ -4050,7 +4118,13 @@ function isProviderQuestionBinding(value) {
|
|
|
4050
4118
|
}
|
|
4051
4119
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4052
4120
|
0 && (module.exports = {
|
|
4121
|
+
ASSISTANT_ACCOUNT_SLOT,
|
|
4122
|
+
ASSISTANT_FOLLOWER_ALLOWED_OPS,
|
|
4053
4123
|
ASSISTANT_OWNER_VERBS,
|
|
4124
|
+
ASSISTANT_REMOTE_FOLLOW_COMMAND,
|
|
4125
|
+
ASSISTANT_REMOTE_PROJECT_ACCESS_COMMAND,
|
|
4126
|
+
ASSISTANT_REMOTE_PROJECT_CATALOG_COMMAND,
|
|
4127
|
+
ASSISTANT_REMOTE_PROJECT_COMMAND,
|
|
4054
4128
|
ASSISTANT_REVIEW_TURN_VERBS,
|
|
4055
4129
|
ASSISTANT_SESSION_ID_ARG,
|
|
4056
4130
|
ASSISTANT_SESSION_ID_ENV,
|
|
@@ -4259,11 +4333,13 @@ function isProviderQuestionBinding(value) {
|
|
|
4259
4333
|
expandDaemonIdForms,
|
|
4260
4334
|
findOwnershipConflicts,
|
|
4261
4335
|
foldKeyedDoc,
|
|
4336
|
+
followedRemoteProjectKey,
|
|
4262
4337
|
formatQuotaAccount,
|
|
4263
4338
|
hasGitStatusEvidence,
|
|
4264
4339
|
hasWorkerProtocolFooter,
|
|
4265
4340
|
interpolateString,
|
|
4266
4341
|
isActionableProviderApproval,
|
|
4342
|
+
isAssistantFollowerAllowedOp,
|
|
4267
4343
|
isAssistantTool,
|
|
4268
4344
|
isBlockedStatus,
|
|
4269
4345
|
isBusyStatus,
|
|
@@ -4387,6 +4463,7 @@ function isProviderQuestionBinding(value) {
|
|
|
4387
4463
|
retiredMeshToolError,
|
|
4388
4464
|
sanitizeModelIdentifier,
|
|
4389
4465
|
sanitizeRefusalCode,
|
|
4466
|
+
sanitizeRemoteRepoIdentity,
|
|
4390
4467
|
scoreGitStatusCandidate,
|
|
4391
4468
|
scoreGitUpstreamFreshness,
|
|
4392
4469
|
sessionIdsEquivalent,
|