@indigoai-us/hq-cli 5.342.4 → 5.342.6
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/CHANGELOG.md +16 -0
- package/dist/command-catalog.generated.d.ts +42 -0
- package/dist/command-catalog.generated.js +51 -0
- package/dist/commands/bot.js +1 -0
- package/dist/commands/core-derive-trigger-facts-command.js +9 -0
- package/dist/commands/mesh.js +20 -1
- package/dist/commands/people.d.ts +1 -1
- package/dist/commands/people.js +8 -4
- package/dist/commands/safe-extract.d.ts +5 -7
- package/dist/commands/safe-extract.js +7 -13
- package/dist/fast-scaffold.js +18 -0
- package/dist/lib/bot/run.js +1 -1
- package/dist/lib/mesh/api.d.ts +7 -0
- package/dist/lib/mesh/api.js +8 -0
- package/dist/utils/resident-package-preload.js +1 -22
- package/dist/utils/run-bundled-script.js +2 -2
- package/dist/utils/self-update.js +1 -1
- package/dist/utils/version-gate.d.ts +1 -1
- package/dist/utils/version-gate.js +7 -9
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [5.342.6] — 2026-10-04
|
|
6
|
+
- Add `hq mesh project member add` to add an active company member to a project.
|
|
7
|
+
|
|
8
|
+
- With `cli.company-errors-sdk-warning` enabled, `hq people` now scopes to a sole cloud membership when the local company manifest is missing.
|
|
9
|
+
- Run the package-use lease macOS and Windows checks on pull requests only when lease inputs change, while retaining both checks on main pushes.
|
|
10
|
+
- Keep `hq secrets env --company <slug>` on the lightweight fast route when the company option follows `env`.
|
|
11
|
+
|
|
12
|
+
## [5.342.5] — 2026-10-04
|
|
13
|
+
|
|
14
|
+
- Keep pnpm v11 global install detection and Windows drive-path tar extraction unconditional; remove their legacy opt-outs.
|
|
15
|
+
|
|
16
|
+
- Pass explicit hook stdin to bundled shell companions through a real pipe on Windows.
|
|
17
|
+
- Run the paired fast-route benchmark only when its executable or build inputs change.
|
|
18
|
+
- Limit `hq mcp serve` resident preloads to its request handler modules; hosted MCP client dependencies remain in the daemon process.
|
|
19
|
+
- Keep a bot's local identity config aligned with reissued credentials during `hq bot restore --all`, preventing heartbeat identity drift.
|
|
20
|
+
|
|
5
21
|
## [5.342.4] — 2026-10-04
|
|
6
22
|
|
|
7
23
|
## [5.342.3] — 2026-10-04
|
|
@@ -9296,6 +9296,48 @@ export declare const COMMAND_CATALOG: readonly [{
|
|
|
9296
9296
|
readonly hidden: false;
|
|
9297
9297
|
}];
|
|
9298
9298
|
readonly subcommands: readonly [];
|
|
9299
|
+
}, {
|
|
9300
|
+
readonly name: "member";
|
|
9301
|
+
readonly description: "Manage project members";
|
|
9302
|
+
readonly aliases: readonly [];
|
|
9303
|
+
readonly hidden: false;
|
|
9304
|
+
readonly helpOption: true;
|
|
9305
|
+
readonly helpCommand: true;
|
|
9306
|
+
readonly usage: "[options] [command]";
|
|
9307
|
+
readonly helpText: readonly [];
|
|
9308
|
+
readonly arguments: readonly [];
|
|
9309
|
+
readonly options: readonly [];
|
|
9310
|
+
readonly subcommands: readonly [{
|
|
9311
|
+
readonly name: "add";
|
|
9312
|
+
readonly description: "Add an active company member to a project";
|
|
9313
|
+
readonly aliases: readonly [];
|
|
9314
|
+
readonly hidden: false;
|
|
9315
|
+
readonly helpOption: true;
|
|
9316
|
+
readonly helpCommand: false;
|
|
9317
|
+
readonly usage: "[options] <projectId> <personUid>";
|
|
9318
|
+
readonly helpText: readonly [];
|
|
9319
|
+
readonly arguments: readonly [{
|
|
9320
|
+
readonly name: "projectId";
|
|
9321
|
+
readonly required: true;
|
|
9322
|
+
readonly variadic: false;
|
|
9323
|
+
readonly description: "";
|
|
9324
|
+
}, {
|
|
9325
|
+
readonly name: "personUid";
|
|
9326
|
+
readonly required: true;
|
|
9327
|
+
readonly variadic: false;
|
|
9328
|
+
readonly description: "";
|
|
9329
|
+
}];
|
|
9330
|
+
readonly options: readonly [{
|
|
9331
|
+
readonly flags: "--company <slug|uid>";
|
|
9332
|
+
readonly description: "Company slug or cloud uid";
|
|
9333
|
+
readonly hidden: false;
|
|
9334
|
+
}, {
|
|
9335
|
+
readonly flags: "--json";
|
|
9336
|
+
readonly description: "Print machine-readable JSON";
|
|
9337
|
+
readonly hidden: false;
|
|
9338
|
+
}];
|
|
9339
|
+
readonly subcommands: readonly [];
|
|
9340
|
+
}];
|
|
9299
9341
|
}];
|
|
9300
9342
|
}, {
|
|
9301
9343
|
readonly name: "doctor";
|
|
@@ -11271,6 +11271,57 @@ export const COMMAND_CATALOG = [
|
|
|
11271
11271
|
}
|
|
11272
11272
|
],
|
|
11273
11273
|
"subcommands": []
|
|
11274
|
+
},
|
|
11275
|
+
{
|
|
11276
|
+
"name": "member",
|
|
11277
|
+
"description": "Manage project members",
|
|
11278
|
+
"aliases": [],
|
|
11279
|
+
"hidden": false,
|
|
11280
|
+
"helpOption": true,
|
|
11281
|
+
"helpCommand": true,
|
|
11282
|
+
"usage": "[options] [command]",
|
|
11283
|
+
"helpText": [],
|
|
11284
|
+
"arguments": [],
|
|
11285
|
+
"options": [],
|
|
11286
|
+
"subcommands": [
|
|
11287
|
+
{
|
|
11288
|
+
"name": "add",
|
|
11289
|
+
"description": "Add an active company member to a project",
|
|
11290
|
+
"aliases": [],
|
|
11291
|
+
"hidden": false,
|
|
11292
|
+
"helpOption": true,
|
|
11293
|
+
"helpCommand": false,
|
|
11294
|
+
"usage": "[options] <projectId> <personUid>",
|
|
11295
|
+
"helpText": [],
|
|
11296
|
+
"arguments": [
|
|
11297
|
+
{
|
|
11298
|
+
"name": "projectId",
|
|
11299
|
+
"required": true,
|
|
11300
|
+
"variadic": false,
|
|
11301
|
+
"description": ""
|
|
11302
|
+
},
|
|
11303
|
+
{
|
|
11304
|
+
"name": "personUid",
|
|
11305
|
+
"required": true,
|
|
11306
|
+
"variadic": false,
|
|
11307
|
+
"description": ""
|
|
11308
|
+
}
|
|
11309
|
+
],
|
|
11310
|
+
"options": [
|
|
11311
|
+
{
|
|
11312
|
+
"flags": "--company <slug|uid>",
|
|
11313
|
+
"description": "Company slug or cloud uid",
|
|
11314
|
+
"hidden": false
|
|
11315
|
+
},
|
|
11316
|
+
{
|
|
11317
|
+
"flags": "--json",
|
|
11318
|
+
"description": "Print machine-readable JSON",
|
|
11319
|
+
"hidden": false
|
|
11320
|
+
}
|
|
11321
|
+
],
|
|
11322
|
+
"subcommands": []
|
|
11323
|
+
}
|
|
11324
|
+
]
|
|
11274
11325
|
}
|
|
11275
11326
|
]
|
|
11276
11327
|
},
|
package/dist/commands/bot.js
CHANGED
|
@@ -1656,6 +1656,7 @@ async function repairLocalBot(name, api, bot, daemon) {
|
|
|
1656
1656
|
catch (err) {
|
|
1657
1657
|
throw credentialError(err, name);
|
|
1658
1658
|
}
|
|
1659
|
+
writeBotConfig(dir, { ...config, agentUid: bot.agentUid });
|
|
1659
1660
|
writeBotCreds(dir, {
|
|
1660
1661
|
username: reissued.identity.cognitoUsername,
|
|
1661
1662
|
secret: reissued.identity.secret,
|
|
@@ -15,11 +15,14 @@ export function registerCoreDeriveTriggerFactsCommand(core) {
|
|
|
15
15
|
.action(async (args = [], _options, commandContext) => {
|
|
16
16
|
if (!await coreNativeHookHelpersEnabled()) {
|
|
17
17
|
const root = liveRoot();
|
|
18
|
+
const stdin = process.platform === "win32" ? await readStdin() : undefined;
|
|
18
19
|
const result = runBundledScript({
|
|
19
20
|
asset: DERIVE_TRIGGER_FACTS_ASSET,
|
|
20
21
|
args: commandContext.args.length ? commandContext.args : args,
|
|
21
22
|
cwd: root,
|
|
22
23
|
hqRoot: root,
|
|
24
|
+
msysScriptPath: process.platform === "win32",
|
|
25
|
+
...(stdin !== undefined ? { stdin } : {}),
|
|
23
26
|
});
|
|
24
27
|
if (result.code !== 0)
|
|
25
28
|
process.exit(result.code);
|
|
@@ -44,4 +47,10 @@ export function registerCoreDeriveTriggerFactsCommand(core) {
|
|
|
44
47
|
});
|
|
45
48
|
describeCoreCommand(command, { execution: "native", asset: DERIVE_TRIGGER_FACTS_ASSET, root: "live" });
|
|
46
49
|
}
|
|
50
|
+
async function readStdin() {
|
|
51
|
+
const chunks = [];
|
|
52
|
+
for await (const chunk of process.stdin)
|
|
53
|
+
chunks.push(chunk);
|
|
54
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
55
|
+
}
|
|
47
56
|
//# sourceMappingURL=core-derive-trigger-facts-command.js.map
|
package/dist/commands/mesh.js
CHANGED
|
@@ -13,7 +13,7 @@ import { CLI_VERSION } from "../cli-version.js";
|
|
|
13
13
|
import chalk from "chalk";
|
|
14
14
|
import { ensureCognitoToken, isExpiring, isMachineIdentity, loadCachedTokens, } from "../utils/cognito-session.js";
|
|
15
15
|
import * as readline from "node:readline/promises";
|
|
16
|
-
import { STORY_STATUSES, appendThreadEvent, ensureProjectThread, eventPayload, getProjectView, listActiveMembershipCompanies, listActiveThreads, patchStory, putProjectView, registerMeshProject, resolveActiveMembershipCompany, resolveMeshPrincipalUid, warmMeshConversationCache, } from "../lib/mesh/api.js";
|
|
16
|
+
import { STORY_STATUSES, appendThreadEvent, addProjectMember, ensureProjectThread, eventPayload, getProjectView, listActiveMembershipCompanies, listActiveThreads, patchStory, putProjectView, registerMeshProject, resolveActiveMembershipCompany, resolveMeshPrincipalUid, warmMeshConversationCache, } from "../lib/mesh/api.js";
|
|
17
17
|
import { closeSupersededProjectThread, ensureMissingBoardStories, ensureProjectBoard, boardStoryStatus, formatStoryStatusChanges, mergeProjectStories, prdSyncEventsThatChangeBoard, } from "../lib/mesh/project-board.js";
|
|
18
18
|
import { mapSourceStoryStatus } from "../lib/mesh/story-status.js";
|
|
19
19
|
import { buildPreflightFixtures } from "../lib/work-context/preflight-contract.js";
|
|
@@ -461,6 +461,17 @@ async function runProjectRegister(projectId, opts) {
|
|
|
461
461
|
}
|
|
462
462
|
console.log(`Work mesh: project ${registration.projectId} registered (${boardState}; channel ${registration.channelId} ${registration.channelCreated ? "created" : "bound"})`);
|
|
463
463
|
}
|
|
464
|
+
async function runProjectMemberAdd(projectId, personUid, opts) {
|
|
465
|
+
const { token, company } = await withCompany(opts);
|
|
466
|
+
const result = await addProjectMember(token, company.companyUid, projectId, personUid);
|
|
467
|
+
if (opts.json) {
|
|
468
|
+
console.log(JSON.stringify({ action: "project.member.add", ...result }, null, 2));
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
console.log(result.added
|
|
472
|
+
? `Work mesh: added ${personUid} to project ${projectId}`
|
|
473
|
+
: `Work mesh: ${personUid} is already a member of project ${projectId}`);
|
|
474
|
+
}
|
|
464
475
|
async function runProjectEnsure(projectId, opts) {
|
|
465
476
|
if (!opts.storiesFile?.trim())
|
|
466
477
|
fail("`--stories-file <prd.json>` is required.");
|
|
@@ -1910,6 +1921,14 @@ export function registerMeshCommand(program) {
|
|
|
1910
1921
|
.option("--channel <channelId>", "Bind the project to an existing company or project channel")
|
|
1911
1922
|
.option("--json", "Print machine-readable JSON")
|
|
1912
1923
|
.action((projectId, opts) => wrap(() => runProjectRegister(projectId, opts))());
|
|
1924
|
+
project
|
|
1925
|
+
.command("member")
|
|
1926
|
+
.description("Manage project members")
|
|
1927
|
+
.command("add <projectId> <personUid>")
|
|
1928
|
+
.description("Add an active company member to a project")
|
|
1929
|
+
.requiredOption("--company <slug|uid>", "Company slug or cloud uid")
|
|
1930
|
+
.option("--json", "Print machine-readable JSON")
|
|
1931
|
+
.action((projectId, personUid, opts) => wrap(() => runProjectMemberAdd(projectId, personUid, opts))());
|
|
1913
1932
|
mesh
|
|
1914
1933
|
.command("doctor")
|
|
1915
1934
|
.description("Warm ~/.hq/work-mesh/cache from hq-pro (directory, inbox, pair DMs). Not `hq doctor`.")
|
|
@@ -18,7 +18,7 @@ export type FetchPeopleRoster = (hqRoot: string, companySlug: string) => Promise
|
|
|
18
18
|
interface PeopleCommandDeps {
|
|
19
19
|
fetchRoster?: FetchPeopleRoster;
|
|
20
20
|
/** Test seam for the shared active-membership ambiguity resolver. */
|
|
21
|
-
resolveMissingManifestMemberships?: () => Promise<void>;
|
|
21
|
+
resolveMissingManifestMemberships?: () => Promise<string | void>;
|
|
22
22
|
companySelectionGuidanceEnabled?: () => boolean;
|
|
23
23
|
}
|
|
24
24
|
interface PeopleLookupOpts {
|
package/dist/commands/people.js
CHANGED
|
@@ -122,12 +122,16 @@ async function resolvePeopleCompanySlug(hqRoot, explicit, localOnly, deps) {
|
|
|
122
122
|
const resolveMemberships = deps.resolveMissingManifestMemberships ??
|
|
123
123
|
(async () => {
|
|
124
124
|
const token = await ensureCognitoToken();
|
|
125
|
-
|
|
125
|
+
return getCompanyUid(token, undefined);
|
|
126
126
|
});
|
|
127
127
|
// The shared resolver throws members-style guidance for multiple active
|
|
128
|
-
// companies.
|
|
129
|
-
//
|
|
130
|
-
await resolveMemberships();
|
|
128
|
+
// companies. With no manifest, its sole-membership UID is also a valid
|
|
129
|
+
// scope for the people roster and company directory.
|
|
130
|
+
const membershipCompany = await resolveMemberships();
|
|
131
|
+
if (message.includes("companies/manifest.yaml not found") &&
|
|
132
|
+
typeof membershipCompany === "string") {
|
|
133
|
+
return membershipCompany;
|
|
134
|
+
}
|
|
131
135
|
}
|
|
132
136
|
throw error;
|
|
133
137
|
}
|
|
@@ -111,12 +111,11 @@ export declare function assertLinkTargetContained(packDir: string, entryAbs: str
|
|
|
111
111
|
/**
|
|
112
112
|
* List a gzip-compressed tarball's entries via `tar -tvf` (no extraction).
|
|
113
113
|
* argv form, never a shell string, keeps hostile filenames out of shell syntax.
|
|
114
|
-
* Windows drive paths use a basename relative to the archive directory
|
|
115
|
-
*
|
|
116
|
-
*
|
|
117
|
-
* Callers can still explicitly opt out with `useRelativeWindowsDrivePath: false`.
|
|
114
|
+
* Windows drive paths always use a basename relative to the archive directory.
|
|
115
|
+
* GNU tar cannot parse `C:\\...` as remote `host:path`, and Windows' bundled
|
|
116
|
+
* bsdtar accepts the same relative argv without GNU-only `--force-local`.
|
|
118
117
|
*/
|
|
119
|
-
export declare function listTarball(tarballPath: string, opts?: Pick<SafeExtractOptions, 'platform' | '
|
|
118
|
+
export declare function listTarball(tarballPath: string, opts?: Pick<SafeExtractOptions, 'platform' | 'execFileSync'>): TarEntry[];
|
|
120
119
|
/**
|
|
121
120
|
* Pre-flight validation against the entry headers. Enforces (a) containment of
|
|
122
121
|
* every entry name under `targetDir`, (b) containment of every link target
|
|
@@ -134,9 +133,8 @@ export declare function validateEntries(entries: TarEntry[], targetDir: string,
|
|
|
134
133
|
export declare function assertExtractContained(stagingDir: string): void;
|
|
135
134
|
export interface SafeExtractOptions {
|
|
136
135
|
caps?: ExtractCaps;
|
|
137
|
-
/** Test
|
|
136
|
+
/** Test seam for platform-specific argv construction. */
|
|
138
137
|
platform?: NodeJS.Platform;
|
|
139
|
-
useRelativeWindowsDrivePath?: boolean;
|
|
140
138
|
execFileSync?: typeof execFileSync;
|
|
141
139
|
/**
|
|
142
140
|
* Test seam: invoked AFTER `tar` extracts into the staging dir but BEFORE
|
|
@@ -203,10 +203,8 @@ export function assertLinkTargetContained(packDir, entryAbs, linkTarget) {
|
|
|
203
203
|
`"${linkTarget}" -> "${resolvedTarget}", outside pack dir "${path.resolve(packDir)}".`);
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
|
-
function tarballArgvLocation(tarballPath, platform
|
|
207
|
-
if (platform === 'win32' &&
|
|
208
|
-
useRelativeWindowsDrivePath &&
|
|
209
|
-
/^[A-Za-z]:[\\/]/.test(tarballPath)) {
|
|
206
|
+
function tarballArgvLocation(tarballPath, platform) {
|
|
207
|
+
if (platform === 'win32' && /^[A-Za-z]:[\\/]/.test(tarballPath)) {
|
|
210
208
|
return {
|
|
211
209
|
archiveArg: path.win32.basename(tarballPath),
|
|
212
210
|
cwd: path.win32.dirname(tarballPath),
|
|
@@ -217,15 +215,13 @@ function tarballArgvLocation(tarballPath, platform, useRelativeWindowsDrivePath)
|
|
|
217
215
|
/**
|
|
218
216
|
* List a gzip-compressed tarball's entries via `tar -tvf` (no extraction).
|
|
219
217
|
* argv form, never a shell string, keeps hostile filenames out of shell syntax.
|
|
220
|
-
* Windows drive paths use a basename relative to the archive directory
|
|
221
|
-
*
|
|
222
|
-
*
|
|
223
|
-
* Callers can still explicitly opt out with `useRelativeWindowsDrivePath: false`.
|
|
218
|
+
* Windows drive paths always use a basename relative to the archive directory.
|
|
219
|
+
* GNU tar cannot parse `C:\\...` as remote `host:path`, and Windows' bundled
|
|
220
|
+
* bsdtar accepts the same relative argv without GNU-only `--force-local`.
|
|
224
221
|
*/
|
|
225
222
|
export function listTarball(tarballPath, opts = {}) {
|
|
226
223
|
const platform = opts.platform ?? process.platform;
|
|
227
|
-
const
|
|
228
|
-
const location = tarballArgvLocation(tarballPath, platform, useRelativeWindowsDrivePath);
|
|
224
|
+
const location = tarballArgvLocation(tarballPath, platform);
|
|
229
225
|
const out = (opts.execFileSync ?? execFileSync)('tar', ['-tvf', location.archiveArg], {
|
|
230
226
|
encoding: 'utf-8',
|
|
231
227
|
maxBuffer: 64 * 1024 * 1024,
|
|
@@ -329,13 +325,11 @@ export function safeExtractTarball(tarballPath, finalDir, opts = {}) {
|
|
|
329
325
|
}
|
|
330
326
|
// Resolve once so listing and extraction use the same archive location.
|
|
331
327
|
const platform = opts.platform ?? process.platform;
|
|
332
|
-
const useRelativeWindowsDrivePath = opts.useRelativeWindowsDrivePath ?? true;
|
|
333
328
|
const exec = opts.execFileSync ?? execFileSync;
|
|
334
|
-
const location = tarballArgvLocation(tarballPath, platform
|
|
329
|
+
const location = tarballArgvLocation(tarballPath, platform);
|
|
335
330
|
// 1. Pre-flight against headers (no bytes written yet).
|
|
336
331
|
const entries = listTarball(tarballPath, {
|
|
337
332
|
platform,
|
|
338
|
-
useRelativeWindowsDrivePath,
|
|
339
333
|
execFileSync: exec,
|
|
340
334
|
});
|
|
341
335
|
validateEntries(entries, finalDir, caps);
|
package/dist/fast-scaffold.js
CHANGED
|
@@ -343,6 +343,24 @@ export function parseSecretsEnvFastRequest(argv) {
|
|
|
343
343
|
const arg = argv[index];
|
|
344
344
|
if (arg === "-h" || arg === "--help" || arg === "--")
|
|
345
345
|
return null;
|
|
346
|
+
// Commander accepts the parent secrets scope option after the `env`
|
|
347
|
+
// subcommand too. Keep that valid spelling on the fast route.
|
|
348
|
+
if (arg === "--company") {
|
|
349
|
+
const value = argv[index + 1];
|
|
350
|
+
if (!value || value.startsWith("-") || hasPersonalScope)
|
|
351
|
+
return null;
|
|
352
|
+
scope.company = value;
|
|
353
|
+
index += 2;
|
|
354
|
+
continue;
|
|
355
|
+
}
|
|
356
|
+
if (arg?.startsWith("--company=")) {
|
|
357
|
+
const value = arg.slice("--company=".length);
|
|
358
|
+
if (!value || hasPersonalScope)
|
|
359
|
+
return null;
|
|
360
|
+
scope.company = value;
|
|
361
|
+
index += 1;
|
|
362
|
+
continue;
|
|
363
|
+
}
|
|
346
364
|
let option;
|
|
347
365
|
let value;
|
|
348
366
|
if (arg === "--only" || arg === "--script" || arg === "--script-id") {
|
package/dist/lib/bot/run.js
CHANGED
|
@@ -540,7 +540,7 @@ export async function runBot(deps) {
|
|
|
540
540
|
configuredAgentUid: config.agentUid,
|
|
541
541
|
...(err.tokenAgentUid ? { tokenAgentUid: err.tokenAgentUid } : {}),
|
|
542
542
|
agentUidSource: deps.agentUidSource ?? "config_file",
|
|
543
|
-
credsSource: deps.credsSource ?? "
|
|
543
|
+
credsSource: deps.credsSource ?? "explicit",
|
|
544
544
|
});
|
|
545
545
|
break;
|
|
546
546
|
}
|
package/dist/lib/mesh/api.d.ts
CHANGED
|
@@ -154,6 +154,13 @@ export declare function patchStoryStatus(token: string, companyUid: string, proj
|
|
|
154
154
|
}>;
|
|
155
155
|
/** Read the full durable Board view before preparing a replacement PUT. */
|
|
156
156
|
export declare function getProjectView(token: string, companyUid: string, projectId: string): Promise<MeshProjectView>;
|
|
157
|
+
/** Add an active company member to the project's Work Mesh channel. */
|
|
158
|
+
export declare function addProjectMember(token: string, companyUid: string, projectId: string, personUid: string): Promise<{
|
|
159
|
+
ok: true;
|
|
160
|
+
projectId: string;
|
|
161
|
+
personUid: string;
|
|
162
|
+
added: boolean;
|
|
163
|
+
}>;
|
|
157
164
|
/** Replace a project's durable Board view and keep the local project cache current. */
|
|
158
165
|
export declare function putProjectView(token: string, companyUid: string, projectId: string, input: {
|
|
159
166
|
name?: string;
|
package/dist/lib/mesh/api.js
CHANGED
|
@@ -465,6 +465,14 @@ export async function getProjectView(token, companyUid, projectId) {
|
|
|
465
465
|
throw new Error("Work mesh returned an invalid project view");
|
|
466
466
|
return projectViewFromResponse(view, companyUid, projectId);
|
|
467
467
|
}
|
|
468
|
+
/** Add an active company member to the project's Work Mesh channel. */
|
|
469
|
+
export async function addProjectMember(token, companyUid, projectId, personUid) {
|
|
470
|
+
const result = asRecord(await meshJson(token, `/v1/work-mesh/projects/${encodeURIComponent(projectId)}`, { method: "PUT", body: { operation: "add-member", companyUid, personUid } }));
|
|
471
|
+
if (result?.ok !== true || typeof result.added !== "boolean") {
|
|
472
|
+
throw new Error("Work mesh returned an invalid project membership result");
|
|
473
|
+
}
|
|
474
|
+
return { ok: true, projectId, personUid, added: result.added };
|
|
475
|
+
}
|
|
468
476
|
/** Replace a project's durable Board view and keep the local project cache current. */
|
|
469
477
|
export async function putProjectView(token, companyUid, projectId, input) {
|
|
470
478
|
const { expectedVersion, ...document } = input;
|
|
@@ -1,19 +1,7 @@
|
|
|
1
1
|
/** Package imports reachable lazily from each resident command's runtime graph. */
|
|
2
2
|
export const RESIDENT_PACKAGE_MODULES = {
|
|
3
3
|
bot: ["../lib/flag-registry.js", "../commands/access.js", "../sentry.js", "open"],
|
|
4
|
-
mcp: [
|
|
5
|
-
"../lib/mcp/tools.js",
|
|
6
|
-
"../lib/mcp/prompts.js",
|
|
7
|
-
"../utils/cognito-session.js",
|
|
8
|
-
"../lib/daemon/mcp-oauth.js",
|
|
9
|
-
"../commands/access.js",
|
|
10
|
-
"../lib/flag-registry.js",
|
|
11
|
-
"@modelcontextprotocol/sdk/client/index.js",
|
|
12
|
-
"@modelcontextprotocol/sdk/client/streamableHttp.js",
|
|
13
|
-
"../sentry.js",
|
|
14
|
-
"open",
|
|
15
|
-
"./staged-npm-install.js",
|
|
16
|
-
],
|
|
4
|
+
mcp: ["../lib/mcp/tools.js", "../lib/mcp/prompts.js"],
|
|
17
5
|
};
|
|
18
6
|
const LOADERS = {
|
|
19
7
|
bot: [
|
|
@@ -25,15 +13,6 @@ const LOADERS = {
|
|
|
25
13
|
mcp: [
|
|
26
14
|
() => import("../lib/mcp/tools.js"),
|
|
27
15
|
() => import("../lib/mcp/prompts.js"),
|
|
28
|
-
() => import("../utils/cognito-session.js"),
|
|
29
|
-
() => import("../lib/daemon/mcp-oauth.js"),
|
|
30
|
-
() => import("../commands/access.js"),
|
|
31
|
-
() => import("../lib/flag-registry.js"),
|
|
32
|
-
() => import("@modelcontextprotocol/sdk/client/index.js"),
|
|
33
|
-
() => import("@modelcontextprotocol/sdk/client/streamableHttp.js"),
|
|
34
|
-
() => import("../sentry.js"),
|
|
35
|
-
() => import("open"),
|
|
36
|
-
() => import("./staged-npm-install.js"),
|
|
37
16
|
],
|
|
38
17
|
};
|
|
39
18
|
export class ResidentPackagePreloadError extends Error {
|
|
@@ -168,8 +168,8 @@ export function runBundledScript(opts) {
|
|
|
168
168
|
try {
|
|
169
169
|
if (opts.stdin !== undefined) {
|
|
170
170
|
// Some scaffold scripts reopen /dev/stdin by pathname. Node's spawnSync
|
|
171
|
-
// input pipe cannot be reopened through /dev/stdin on Linux,
|
|
172
|
-
//
|
|
171
|
+
// input pipe cannot be reopened through /dev/stdin on Git Bash or Linux,
|
|
172
|
+
// so supply a private regular file descriptor to preserve that ABI.
|
|
173
173
|
const sharedMemory = process.platform === "linux" && fs.existsSync("/dev/shm")
|
|
174
174
|
? "/dev/shm"
|
|
175
175
|
: os.tmpdir();
|
|
@@ -372,7 +372,7 @@ function isRecognizedGlobalInstall(install, packageRoot) {
|
|
|
372
372
|
if (!isInsideNodeModules(packageRoot))
|
|
373
373
|
return false;
|
|
374
374
|
if (install.manager === "pnpm")
|
|
375
|
-
return isPnpmManagedPackageDir(packageRoot
|
|
375
|
+
return isPnpmManagedPackageDir(packageRoot);
|
|
376
376
|
if (install.manager === "bun")
|
|
377
377
|
return isBunManagedPackageDir(packageRoot);
|
|
378
378
|
if (!install.prefix)
|
|
@@ -70,7 +70,7 @@ export declare function npmPrefixFromPackageDir(pkgDir: string): string | null;
|
|
|
70
70
|
* i.e. the gate would re-fire and re-install globally on every subsequent run.
|
|
71
71
|
* Those layouts fall through to the ordinary npm-prefix/manual handling.
|
|
72
72
|
*/
|
|
73
|
-
export declare function isPnpmManagedPackageDir(pkgDir: string
|
|
73
|
+
export declare function isPnpmManagedPackageDir(pkgDir: string): boolean;
|
|
74
74
|
/** Whether the running package lives inside Bun's global install tree. */
|
|
75
75
|
export declare function isBunManagedPackageDir(pkgDir: string): boolean;
|
|
76
76
|
/**
|
|
@@ -128,7 +128,7 @@ function findPackageRootForExecutable(bin) {
|
|
|
128
128
|
const packageRoot = findCliPackageRoot(candidate);
|
|
129
129
|
if (packageRoot &&
|
|
130
130
|
samePath(packageRoot, candidate) &&
|
|
131
|
-
isPnpmManagedPackageDir(packageRoot
|
|
131
|
+
isPnpmManagedPackageDir(packageRoot)) {
|
|
132
132
|
return packageRoot;
|
|
133
133
|
}
|
|
134
134
|
}
|
|
@@ -151,7 +151,7 @@ function samePath(left, right) {
|
|
|
151
151
|
: a === b;
|
|
152
152
|
}
|
|
153
153
|
function globalInstallManagerForPath(bin, packageRoot) {
|
|
154
|
-
if (isPnpmManagedPackageDir(packageRoot
|
|
154
|
+
if (isPnpmManagedPackageDir(packageRoot)) {
|
|
155
155
|
return "pnpm";
|
|
156
156
|
}
|
|
157
157
|
if (isBunManagedPackageDir(packageRoot))
|
|
@@ -215,7 +215,7 @@ function pnpmHomeGlobalRoot() {
|
|
|
215
215
|
* i.e. the gate would re-fire and re-install globally on every subsequent run.
|
|
216
216
|
* Those layouts fall through to the ordinary npm-prefix/manual handling.
|
|
217
217
|
*/
|
|
218
|
-
export function isPnpmManagedPackageDir(pkgDir
|
|
218
|
+
export function isPnpmManagedPackageDir(pkgDir) {
|
|
219
219
|
const normalized = pkgDir.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
220
220
|
const segments = normalized.split("/").filter(Boolean);
|
|
221
221
|
// pnpm through v10 uses `global/<digits>`; pnpm v11+ uses
|
|
@@ -228,13 +228,11 @@ export function isPnpmManagedPackageDir(pkgDir, acceptVersionPrefixedGlobalDir =
|
|
|
228
228
|
const globalDirVersion = segments[i + 1];
|
|
229
229
|
if (/^\d+$/.test(globalDirVersion))
|
|
230
230
|
return true;
|
|
231
|
-
if (
|
|
231
|
+
if (/^v\d+$/.test(globalDirVersion))
|
|
232
232
|
return true;
|
|
233
|
-
}
|
|
234
233
|
}
|
|
235
|
-
// PNPM_HOME/global is pnpm's configured global root by construction,
|
|
236
|
-
//
|
|
237
|
-
// documented global/v<major> segment match outside that configured root.
|
|
234
|
+
// PNPM_HOME/global is pnpm's configured global root by construction, even
|
|
235
|
+
// when the version segment is not one of the documented numeric forms.
|
|
238
236
|
const globalRoot = pnpmHomeGlobalRoot();
|
|
239
237
|
if (globalRoot) {
|
|
240
238
|
if (normalized === globalRoot || normalized.startsWith(`${globalRoot}/`)) {
|
|
@@ -361,7 +359,7 @@ export function resolveRunningInstall() {
|
|
|
361
359
|
const packageRoot = findRunningPackageRoot();
|
|
362
360
|
if (!packageRoot)
|
|
363
361
|
return { manager: "npm", prefix: null, packageRoot: null };
|
|
364
|
-
if (isPnpmManagedPackageDir(packageRoot
|
|
362
|
+
if (isPnpmManagedPackageDir(packageRoot)) {
|
|
365
363
|
return { manager: "pnpm", prefix: null, packageRoot };
|
|
366
364
|
}
|
|
367
365
|
if (isBunManagedPackageDir(packageRoot)) {
|