@staff0rd/assist 0.206.0 → 0.206.1
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/index.js +104 -45
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.206.
|
|
9
|
+
version: "0.206.1",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -5463,6 +5463,86 @@ import { basename as basename4 } from "path";
|
|
|
5463
5463
|
// src/shared/splitCompound.ts
|
|
5464
5464
|
import { parse } from "shell-quote";
|
|
5465
5465
|
|
|
5466
|
+
// src/shared/consumeRedirect.ts
|
|
5467
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
5468
|
+
|
|
5469
|
+
// src/shared/isRedirectTargetAllowed.ts
|
|
5470
|
+
function isRedirectTargetAllowed(target, tmp) {
|
|
5471
|
+
if (/^[A-Za-z]:[\\/]/.test(tmp)) return isUnderWindowsTmp(target, tmp);
|
|
5472
|
+
return isUnderPosixTmp(target, tmp);
|
|
5473
|
+
}
|
|
5474
|
+
function isUnderWindowsTmp(target, tmp) {
|
|
5475
|
+
if (!/^[A-Za-z]:[\\/]/.test(target)) return false;
|
|
5476
|
+
const nTmp = normalizeWindowsPath(tmp);
|
|
5477
|
+
const nTarget = normalizeWindowsPath(target);
|
|
5478
|
+
return nTarget === nTmp || nTarget.startsWith(`${nTmp}\\`);
|
|
5479
|
+
}
|
|
5480
|
+
function normalizeWindowsPath(p) {
|
|
5481
|
+
return p.replace(/\//g, "\\").toLowerCase().replace(/\\+$/, "");
|
|
5482
|
+
}
|
|
5483
|
+
function isUnderPosixTmp(target, tmp) {
|
|
5484
|
+
if (!target.startsWith("/")) return false;
|
|
5485
|
+
const nTmp = tmp.replace(/\/+$/, "");
|
|
5486
|
+
return target === nTmp || target.startsWith(`${nTmp}/`);
|
|
5487
|
+
}
|
|
5488
|
+
|
|
5489
|
+
// src/shared/consumeRedirect.ts
|
|
5490
|
+
function consumeRedirect(tokens, opIndex, current) {
|
|
5491
|
+
const target = tokens[opIndex + 1];
|
|
5492
|
+
if (typeof target !== "string") {
|
|
5493
|
+
return { ok: false, error: "unable to parse" };
|
|
5494
|
+
}
|
|
5495
|
+
if (!isRedirectTargetAllowed(target, tmpdir2())) {
|
|
5496
|
+
return {
|
|
5497
|
+
ok: false,
|
|
5498
|
+
error: `redirect target '${target}' is outside the OS temp directory`
|
|
5499
|
+
};
|
|
5500
|
+
}
|
|
5501
|
+
if (current.length > 0 && /^\d$/.test(current[current.length - 1])) {
|
|
5502
|
+
current.pop();
|
|
5503
|
+
}
|
|
5504
|
+
return { ok: true, nextIndex: opIndex + 1 };
|
|
5505
|
+
}
|
|
5506
|
+
|
|
5507
|
+
// src/shared/groupByOperator.ts
|
|
5508
|
+
var SEPARATOR_OPS = /* @__PURE__ */ new Set(["|", "&&", "||", ";"]);
|
|
5509
|
+
var OUTPUT_REDIRECT_OPS = /* @__PURE__ */ new Set([">", ">>"]);
|
|
5510
|
+
var UNPARSEABLE = { ok: false, error: "unable to parse" };
|
|
5511
|
+
function groupByOperator(tokens) {
|
|
5512
|
+
const groups = [[]];
|
|
5513
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
5514
|
+
const step = handleToken(tokens, i, groups);
|
|
5515
|
+
if (!step.ok) return step;
|
|
5516
|
+
i = step.nextIndex;
|
|
5517
|
+
}
|
|
5518
|
+
return { ok: true, groups };
|
|
5519
|
+
}
|
|
5520
|
+
function handleToken(tokens, i, groups) {
|
|
5521
|
+
const token = tokens[i];
|
|
5522
|
+
const op = getOp(token);
|
|
5523
|
+
if (op === void 0) return appendWord(token, groups, i);
|
|
5524
|
+
if (op === "glob") {
|
|
5525
|
+
groups[groups.length - 1].push(token.pattern);
|
|
5526
|
+
return { ok: true, nextIndex: i };
|
|
5527
|
+
}
|
|
5528
|
+
if (SEPARATOR_OPS.has(op)) {
|
|
5529
|
+
groups.push([]);
|
|
5530
|
+
return { ok: true, nextIndex: i };
|
|
5531
|
+
}
|
|
5532
|
+
if (OUTPUT_REDIRECT_OPS.has(op)) {
|
|
5533
|
+
return consumeRedirect(tokens, i, groups[groups.length - 1]);
|
|
5534
|
+
}
|
|
5535
|
+
return UNPARSEABLE;
|
|
5536
|
+
}
|
|
5537
|
+
function appendWord(token, groups, i) {
|
|
5538
|
+
if (typeof token !== "string") return UNPARSEABLE;
|
|
5539
|
+
groups[groups.length - 1].push(token);
|
|
5540
|
+
return { ok: true, nextIndex: i };
|
|
5541
|
+
}
|
|
5542
|
+
function getOp(token) {
|
|
5543
|
+
return typeof token === "object" && token !== null && "op" in token ? token.op : void 0;
|
|
5544
|
+
}
|
|
5545
|
+
|
|
5466
5546
|
// src/shared/hasUnquotedBackticks.ts
|
|
5467
5547
|
var QUOTED_OR_BACKTICK_RE = /\\.|'[^']*'|"[^"]*"|(`)/g;
|
|
5468
5548
|
function hasUnquotedBackticks(command) {
|
|
@@ -5474,17 +5554,17 @@ function hasUnquotedBackticks(command) {
|
|
|
5474
5554
|
}
|
|
5475
5555
|
|
|
5476
5556
|
// src/shared/splitCompound.ts
|
|
5477
|
-
var SEPARATOR_OPS = /* @__PURE__ */ new Set(["|", "&&", "||", ";"]);
|
|
5478
|
-
var UNSAFE_OPS = /* @__PURE__ */ new Set(["(", ")", ">", ">>", "<", "<&", "|&", ">&"]);
|
|
5479
5557
|
var FD_REDIRECT_RE = /\d+>&\d+/g;
|
|
5480
5558
|
var FD_DEVNULL_RE = /\d*>(?:\/dev\/null|\$null)/g;
|
|
5559
|
+
var UNPARSEABLE2 = { ok: false, error: "unable to parse" };
|
|
5481
5560
|
function splitCompound(command) {
|
|
5482
5561
|
const tokens = tokenizeCommand(command);
|
|
5483
|
-
if (!tokens) return
|
|
5484
|
-
const
|
|
5485
|
-
if (!
|
|
5486
|
-
const
|
|
5487
|
-
|
|
5562
|
+
if (!tokens) return UNPARSEABLE2;
|
|
5563
|
+
const grouped = groupByOperator(tokens);
|
|
5564
|
+
if (!grouped.ok) return grouped;
|
|
5565
|
+
const parts = grouped.groups.map((g) => stripEnvPrefix(g).join(" ")).filter((cmd) => cmd !== "");
|
|
5566
|
+
if (parts.length === 0) return UNPARSEABLE2;
|
|
5567
|
+
return { ok: true, parts };
|
|
5488
5568
|
}
|
|
5489
5569
|
function tokenizeCommand(command) {
|
|
5490
5570
|
const trimmed = command.trim().replace(FD_DEVNULL_RE, "").replace(FD_REDIRECT_RE, "");
|
|
@@ -5496,28 +5576,6 @@ function tokenizeCommand(command) {
|
|
|
5496
5576
|
return void 0;
|
|
5497
5577
|
}
|
|
5498
5578
|
}
|
|
5499
|
-
function getOp(token) {
|
|
5500
|
-
return typeof token === "object" && token !== null && "op" in token ? token.op : void 0;
|
|
5501
|
-
}
|
|
5502
|
-
function groupByOperator(tokens) {
|
|
5503
|
-
const groups = [[]];
|
|
5504
|
-
for (const token of tokens) {
|
|
5505
|
-
const op = getOp(token);
|
|
5506
|
-
if (op === void 0) {
|
|
5507
|
-
if (typeof token !== "string") return void 0;
|
|
5508
|
-
groups[groups.length - 1].push(token);
|
|
5509
|
-
} else if (op === "glob") {
|
|
5510
|
-
groups[groups.length - 1].push(token.pattern);
|
|
5511
|
-
} else if (SEPARATOR_OPS.has(op)) {
|
|
5512
|
-
groups.push([]);
|
|
5513
|
-
} else if (UNSAFE_OPS.has(op)) {
|
|
5514
|
-
return void 0;
|
|
5515
|
-
} else {
|
|
5516
|
-
return void 0;
|
|
5517
|
-
}
|
|
5518
|
-
}
|
|
5519
|
-
return groups;
|
|
5520
|
-
}
|
|
5521
5579
|
function stripEnvPrefix(parts) {
|
|
5522
5580
|
let i = 0;
|
|
5523
5581
|
while (i < parts.length && /^[A-Za-z_]\w*=/.test(parts[i])) i++;
|
|
@@ -5895,8 +5953,8 @@ function tryParseInput(raw) {
|
|
|
5895
5953
|
}
|
|
5896
5954
|
}
|
|
5897
5955
|
function decide(toolName, rawCommand) {
|
|
5898
|
-
const
|
|
5899
|
-
if (
|
|
5956
|
+
const result = splitCompound(rawCommand);
|
|
5957
|
+
if (result.ok) return resolvePermission(toolName, result.parts);
|
|
5900
5958
|
return findDeny(toolName, [rawCommand]);
|
|
5901
5959
|
}
|
|
5902
5960
|
async function cliHook() {
|
|
@@ -5926,12 +5984,13 @@ async function cliHook() {
|
|
|
5926
5984
|
// src/commands/cliHook/cliHookCheck.ts
|
|
5927
5985
|
function cliHookCheck(command, toolName = "Bash") {
|
|
5928
5986
|
const trimmed = command.trim();
|
|
5929
|
-
const
|
|
5930
|
-
if (!
|
|
5931
|
-
console.log(
|
|
5987
|
+
const result = splitCompound(trimmed);
|
|
5988
|
+
if (!result.ok) {
|
|
5989
|
+
console.log(`not approved (${result.error})`);
|
|
5932
5990
|
process.exitCode = 1;
|
|
5933
5991
|
return;
|
|
5934
5992
|
}
|
|
5993
|
+
const parts = result.parts;
|
|
5935
5994
|
for (const part of parts) {
|
|
5936
5995
|
const configDeny = matchesConfigDeny(part);
|
|
5937
5996
|
if (configDeny) {
|
|
@@ -8060,7 +8119,7 @@ function parseInspectReport(json) {
|
|
|
8060
8119
|
// src/commands/dotnet/runInspectCode.ts
|
|
8061
8120
|
import { execSync as execSync22 } from "child_process";
|
|
8062
8121
|
import { existsSync as existsSync28, readFileSync as readFileSync25, unlinkSync as unlinkSync5 } from "fs";
|
|
8063
|
-
import { tmpdir as
|
|
8122
|
+
import { tmpdir as tmpdir3 } from "os";
|
|
8064
8123
|
import path29 from "path";
|
|
8065
8124
|
import chalk91 from "chalk";
|
|
8066
8125
|
function assertJbInstalled() {
|
|
@@ -8075,7 +8134,7 @@ function assertJbInstalled() {
|
|
|
8075
8134
|
}
|
|
8076
8135
|
}
|
|
8077
8136
|
function runInspectCode(slnPath, include, swea) {
|
|
8078
|
-
const reportPath = path29.join(
|
|
8137
|
+
const reportPath = path29.join(tmpdir3(), `inspect-${Date.now()}.xml`);
|
|
8079
8138
|
const includeFlag = include ? ` --include="${include}"` : "";
|
|
8080
8139
|
const sweaFlag = swea ? " --swea" : "";
|
|
8081
8140
|
try {
|
|
@@ -8715,7 +8774,7 @@ function registerPrompts(program2) {
|
|
|
8715
8774
|
// src/commands/prs/comment.ts
|
|
8716
8775
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
8717
8776
|
import { unlinkSync as unlinkSync6, writeFileSync as writeFileSync21 } from "fs";
|
|
8718
|
-
import { tmpdir as
|
|
8777
|
+
import { tmpdir as tmpdir4 } from "os";
|
|
8719
8778
|
import { join as join29 } from "path";
|
|
8720
8779
|
|
|
8721
8780
|
// src/commands/prs/shared.ts
|
|
@@ -8788,7 +8847,7 @@ function comment2(path53, line, body) {
|
|
|
8788
8847
|
validateLine(line);
|
|
8789
8848
|
try {
|
|
8790
8849
|
const prId = getCurrentPrNodeId();
|
|
8791
|
-
const queryFile = join29(
|
|
8850
|
+
const queryFile = join29(tmpdir4(), `gh-query-${Date.now()}.graphql`);
|
|
8792
8851
|
writeFileSync21(queryFile, MUTATION);
|
|
8793
8852
|
try {
|
|
8794
8853
|
const result = spawnSync2(
|
|
@@ -8832,7 +8891,7 @@ import { execSync as execSync28 } from "child_process";
|
|
|
8832
8891
|
// src/commands/prs/resolveCommentWithReply.ts
|
|
8833
8892
|
import { execSync as execSync27 } from "child_process";
|
|
8834
8893
|
import { unlinkSync as unlinkSync8, writeFileSync as writeFileSync22 } from "fs";
|
|
8835
|
-
import { tmpdir as
|
|
8894
|
+
import { tmpdir as tmpdir5 } from "os";
|
|
8836
8895
|
import { join as join31 } from "path";
|
|
8837
8896
|
|
|
8838
8897
|
// src/commands/prs/loadCommentsCache.ts
|
|
@@ -8867,7 +8926,7 @@ function replyToComment(org, repo, prNumber, commentId, message) {
|
|
|
8867
8926
|
}
|
|
8868
8927
|
function resolveThread(threadId) {
|
|
8869
8928
|
const mutation = `mutation($threadId: ID!) { resolveReviewThread(input: {threadId: $threadId}) { thread { isResolved } } }`;
|
|
8870
|
-
const queryFile = join31(
|
|
8929
|
+
const queryFile = join31(tmpdir5(), `gh-mutation-${Date.now()}.graphql`);
|
|
8871
8930
|
writeFileSync22(queryFile, mutation);
|
|
8872
8931
|
try {
|
|
8873
8932
|
execSync27(
|
|
@@ -8956,11 +9015,11 @@ import { stringify } from "yaml";
|
|
|
8956
9015
|
// src/commands/prs/fetchThreadIds.ts
|
|
8957
9016
|
import { execSync as execSync29 } from "child_process";
|
|
8958
9017
|
import { unlinkSync as unlinkSync9, writeFileSync as writeFileSync23 } from "fs";
|
|
8959
|
-
import { tmpdir as
|
|
9018
|
+
import { tmpdir as tmpdir6 } from "os";
|
|
8960
9019
|
import { join as join32 } from "path";
|
|
8961
9020
|
var THREAD_QUERY = `query($owner: String!, $repo: String!, $prNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $prNumber) { reviewThreads(first: 100) { nodes { id isResolved comments(first: 100) { nodes { databaseId } } } } } } }`;
|
|
8962
9021
|
function fetchThreadIds(org, repo, prNumber) {
|
|
8963
|
-
const queryFile = join32(
|
|
9022
|
+
const queryFile = join32(tmpdir6(), `gh-query-${Date.now()}.graphql`);
|
|
8964
9023
|
writeFileSync23(queryFile, THREAD_QUERY);
|
|
8965
9024
|
try {
|
|
8966
9025
|
const result = execSync29(
|
|
@@ -13067,7 +13126,7 @@ function registerRun(program2) {
|
|
|
13067
13126
|
// src/commands/screenshot/index.ts
|
|
13068
13127
|
import { execSync as execSync39 } from "child_process";
|
|
13069
13128
|
import { existsSync as existsSync43, mkdirSync as mkdirSync15, unlinkSync as unlinkSync12, writeFileSync as writeFileSync29 } from "fs";
|
|
13070
|
-
import { tmpdir as
|
|
13129
|
+
import { tmpdir as tmpdir7 } from "os";
|
|
13071
13130
|
import { join as join49, resolve as resolve11 } from "path";
|
|
13072
13131
|
import chalk133 from "chalk";
|
|
13073
13132
|
|
|
@@ -13205,7 +13264,7 @@ function buildOutputPath(outputDir, processName) {
|
|
|
13205
13264
|
return resolve11(outputDir, `${processName}-${timestamp}.png`);
|
|
13206
13265
|
}
|
|
13207
13266
|
function runPowerShellScript(processName, outputPath) {
|
|
13208
|
-
const scriptPath = join49(
|
|
13267
|
+
const scriptPath = join49(tmpdir7(), `assist-screenshot-${Date.now()}.ps1`);
|
|
13209
13268
|
writeFileSync29(scriptPath, captureWindowPs1, "utf-8");
|
|
13210
13269
|
try {
|
|
13211
13270
|
execSync39(
|