@staff0rd/assist 0.496.0 → 0.496.2
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/README.md +2 -2
- package/claude/settings.json +0 -1
- package/dist/commands/sessions/web/bundle.js +2 -2
- package/dist/index.js +87 -22
- 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.496.
|
|
9
|
+
version: "0.496.2",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -10848,6 +10848,46 @@ function toSegment(part) {
|
|
|
10848
10848
|
return typeof part === "number" ? { kind: "index", index: part } : { kind: "key", name: String(part) };
|
|
10849
10849
|
}
|
|
10850
10850
|
|
|
10851
|
+
// src/shared/maskConfigSecrets.ts
|
|
10852
|
+
var SECRET_MASK = "<hidden>";
|
|
10853
|
+
function maskConfigSecrets(value, node) {
|
|
10854
|
+
return mapConfigSecrets(value, node, () => SECRET_MASK);
|
|
10855
|
+
}
|
|
10856
|
+
|
|
10857
|
+
// src/shared/scrubConfigSecrets.ts
|
|
10858
|
+
function secretStrings(value, node) {
|
|
10859
|
+
const secrets = [];
|
|
10860
|
+
mapConfigSecrets(value, node, (secret) => {
|
|
10861
|
+
if (typeof secret === "string" && secret !== "") secrets.push(secret);
|
|
10862
|
+
return secret;
|
|
10863
|
+
});
|
|
10864
|
+
return secrets;
|
|
10865
|
+
}
|
|
10866
|
+
function literalAndJsonEncoded(secret) {
|
|
10867
|
+
const encoded = JSON.stringify(secret).slice(1, -1);
|
|
10868
|
+
return encoded === secret ? [secret] : [secret, encoded];
|
|
10869
|
+
}
|
|
10870
|
+
function scrubConfigSecrets(messages, value, node) {
|
|
10871
|
+
const needles = secretStrings(value, node).flatMap(literalAndJsonEncoded).sort((a, b) => b.length - a.length);
|
|
10872
|
+
if (needles.length === 0) return messages;
|
|
10873
|
+
return messages.map(
|
|
10874
|
+
(message3) => needles.reduce(
|
|
10875
|
+
(text17, needle) => text17.split(needle).join(SECRET_MASK),
|
|
10876
|
+
message3
|
|
10877
|
+
)
|
|
10878
|
+
);
|
|
10879
|
+
}
|
|
10880
|
+
|
|
10881
|
+
// src/commands/config/configKeyNode.ts
|
|
10882
|
+
function configKeyNode(key) {
|
|
10883
|
+
return configEntryNode(describeConfigNode(assistConfigSchema), key);
|
|
10884
|
+
}
|
|
10885
|
+
|
|
10886
|
+
// src/commands/config/scrubConfigKeyError.ts
|
|
10887
|
+
function scrubConfigKeyError(error, key, value) {
|
|
10888
|
+
return scrubConfigSecrets([error], value, configKeyNode(key))[0];
|
|
10889
|
+
}
|
|
10890
|
+
|
|
10851
10891
|
// src/commands/config/coerceConfigValue.ts
|
|
10852
10892
|
var EDITABLE_TYPES = /* @__PURE__ */ new Set([
|
|
10853
10893
|
"string",
|
|
@@ -10857,6 +10897,11 @@ var EDITABLE_TYPES = /* @__PURE__ */ new Set([
|
|
|
10857
10897
|
"union"
|
|
10858
10898
|
]);
|
|
10859
10899
|
function coerceConfigValue(key, raw) {
|
|
10900
|
+
const result = coerceValue(key, raw);
|
|
10901
|
+
if (result.ok) return result;
|
|
10902
|
+
return { ok: false, error: scrubConfigKeyError(result.error, key, raw) };
|
|
10903
|
+
}
|
|
10904
|
+
function coerceValue(key, raw) {
|
|
10860
10905
|
const leaf = describeConfigLeaves(assistConfigSchema).find(
|
|
10861
10906
|
(candidate) => candidate.key === key
|
|
10862
10907
|
);
|
|
@@ -10917,7 +10962,7 @@ function restoreConfigSecrets(value, stored, node) {
|
|
|
10917
10962
|
|
|
10918
10963
|
// src/commands/config/restoreConfigWriteSecrets.ts
|
|
10919
10964
|
function restoreConfigWriteSecrets(key, value, cwd) {
|
|
10920
|
-
const node =
|
|
10965
|
+
const node = configKeyNode(key);
|
|
10921
10966
|
if (!node) return value;
|
|
10922
10967
|
const stored = loadConfigFrom(cwd);
|
|
10923
10968
|
return restoreConfigSecrets(value, getNestedValue(stored, key), node);
|
|
@@ -10975,9 +11020,10 @@ function setNestedValue(obj, path71, value) {
|
|
|
10975
11020
|
function validateConfig(updated, key, schema2 = assistConfigSchema) {
|
|
10976
11021
|
const result = schema2.safeParse(updated);
|
|
10977
11022
|
if (result.success) return { ok: true };
|
|
11023
|
+
const errors = result.error.issues.map((issue) => formatIssue2(issue, key));
|
|
10978
11024
|
return {
|
|
10979
11025
|
ok: false,
|
|
10980
|
-
errors:
|
|
11026
|
+
errors: scrubConfigSecrets(errors, updated, describeConfigNode(schema2))
|
|
10981
11027
|
};
|
|
10982
11028
|
}
|
|
10983
11029
|
function formatIssue2(issue, key) {
|
|
@@ -15121,10 +15167,17 @@ function parsePerms(entries) {
|
|
|
15121
15167
|
return map;
|
|
15122
15168
|
}
|
|
15123
15169
|
|
|
15170
|
+
// src/shared/revealsConfigSecret.ts
|
|
15171
|
+
var REVEAL_RE = /^assist\s+config\s+get\b.*\s--reveal\b/;
|
|
15172
|
+
function revealsConfigSecret(command) {
|
|
15173
|
+
return REVEAL_RE.test(command);
|
|
15174
|
+
}
|
|
15175
|
+
|
|
15124
15176
|
// src/shared/isApprovedRead.ts
|
|
15125
15177
|
var READ_RE = /^Read\((.+)\)$/;
|
|
15126
15178
|
var SAFE_BUILTINS = /* @__PURE__ */ new Set(["true", "false"]);
|
|
15127
15179
|
function isApprovedRead(command, toolName = "Bash") {
|
|
15180
|
+
if (revealsConfigSecret(command)) return void 0;
|
|
15128
15181
|
if (SAFE_BUILTINS.has(command)) return `safe shell builtin: ${command}`;
|
|
15129
15182
|
if (isCdToCwd(command)) return "cd to current directory";
|
|
15130
15183
|
const cdRead = isCdToReadAllowedDir(command);
|
|
@@ -16671,14 +16724,6 @@ function registerComplexity(program2) {
|
|
|
16671
16724
|
|
|
16672
16725
|
// src/commands/config/index.ts
|
|
16673
16726
|
import { stringify as stringifyYaml2 } from "yaml";
|
|
16674
|
-
|
|
16675
|
-
// src/shared/maskConfigSecrets.ts
|
|
16676
|
-
var SECRET_MASK = "<hidden>";
|
|
16677
|
-
function maskConfigSecrets(value, node) {
|
|
16678
|
-
return mapConfigSecrets(value, node, () => SECRET_MASK);
|
|
16679
|
-
}
|
|
16680
|
-
|
|
16681
|
-
// src/commands/config/index.ts
|
|
16682
16727
|
function configList() {
|
|
16683
16728
|
const config = maskConfigSecrets(
|
|
16684
16729
|
loadConfig(),
|
|
@@ -16689,16 +16734,21 @@ function configList() {
|
|
|
16689
16734
|
|
|
16690
16735
|
// src/commands/config/configGet.ts
|
|
16691
16736
|
import chalk131 from "chalk";
|
|
16737
|
+
|
|
16738
|
+
// src/commands/config/maskConfigKeySecrets.ts
|
|
16739
|
+
function maskConfigKeySecrets(key, value) {
|
|
16740
|
+
return maskConfigSecrets(value, configKeyNode(key));
|
|
16741
|
+
}
|
|
16742
|
+
|
|
16743
|
+
// src/commands/config/configGet.ts
|
|
16692
16744
|
function configGet(key, options2 = {}) {
|
|
16693
16745
|
const value = requireNestedValue(
|
|
16694
16746
|
loadConfig(),
|
|
16695
16747
|
key
|
|
16696
16748
|
);
|
|
16697
|
-
console.log(
|
|
16698
|
-
|
|
16699
|
-
|
|
16700
|
-
const node = configEntryNode(describeConfigNode(assistConfigSchema), key);
|
|
16701
|
-
return maskConfigSecrets(value, node);
|
|
16749
|
+
console.log(
|
|
16750
|
+
formatOutput(options2.reveal ? value : maskConfigKeySecrets(key, value))
|
|
16751
|
+
);
|
|
16702
16752
|
}
|
|
16703
16753
|
function formatOutput(value) {
|
|
16704
16754
|
return typeof value === "object" && value !== null ? JSON.stringify(value, null, 2) : String(value);
|
|
@@ -16769,9 +16819,8 @@ function configSet(key, value, options2 = {}) {
|
|
|
16769
16819
|
if (!coercion.ok) exitWithConfigErrors([coercion.error]);
|
|
16770
16820
|
const coerced = coercion.value;
|
|
16771
16821
|
const target = resolved.useRepo ? `repo: ${applyRepoOrExit(resolved.key, coerced, resolved.repoName)}` : applyOrExit(resolved.key, coerced, options2.global ?? false);
|
|
16772
|
-
|
|
16773
|
-
|
|
16774
|
-
);
|
|
16822
|
+
const shown = JSON.stringify(maskConfigKeySecrets(resolved.key, coerced));
|
|
16823
|
+
console.log(chalk133.green(`Set ${resolved.key} = ${shown} (${target})`));
|
|
16775
16824
|
}
|
|
16776
16825
|
function applyOrExit(key, coerced, global) {
|
|
16777
16826
|
const result = applyConfigSet(key, coerced, global);
|
|
@@ -30192,12 +30241,11 @@ function deriveTranscriptStatus(entries, opts = {}) {
|
|
|
30192
30241
|
if (ev.kind === "toolResult") return null;
|
|
30193
30242
|
if (ev.stopReason != null && TURN_END_STOP_REASONS.has(ev.stopReason))
|
|
30194
30243
|
return "waiting";
|
|
30244
|
+
if (opts.permissionActive) return "waiting";
|
|
30195
30245
|
const resolved = resolvedToolUseIds(events, lastIdx);
|
|
30196
30246
|
const pending = ev.toolUses.filter((tool) => !resolved.has(tool.id));
|
|
30197
|
-
if (pending.length === 0) return "running";
|
|
30198
30247
|
if (pending.some((tool) => tool.name === ASK_USER_QUESTION2))
|
|
30199
30248
|
return "waiting";
|
|
30200
|
-
if (opts.permissionActive) return "waiting";
|
|
30201
30249
|
return "running";
|
|
30202
30250
|
}
|
|
30203
30251
|
function lastDecisiveIndex(events) {
|
|
@@ -30275,6 +30323,19 @@ function readTranscriptTailSync(filePath, maxBytes = DEFAULT_MAX_BYTES) {
|
|
|
30275
30323
|
}
|
|
30276
30324
|
}
|
|
30277
30325
|
|
|
30326
|
+
// src/commands/sessions/shared/transcriptTailFingerprint.ts
|
|
30327
|
+
var CONVERSATION_TYPES = /* @__PURE__ */ new Set(["user", "assistant"]);
|
|
30328
|
+
function transcriptTailFingerprint(entries) {
|
|
30329
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
30330
|
+
const entry = entries[i];
|
|
30331
|
+
if (entry.isSidechain || entry.isMeta) continue;
|
|
30332
|
+
if (typeof entry.type !== "string" || !CONVERSATION_TYPES.has(entry.type))
|
|
30333
|
+
continue;
|
|
30334
|
+
return typeof entry.uuid === "string" && entry.uuid ? entry.uuid : null;
|
|
30335
|
+
}
|
|
30336
|
+
return null;
|
|
30337
|
+
}
|
|
30338
|
+
|
|
30278
30339
|
// src/commands/sessions/daemon/reconcileTranscriptStatus.ts
|
|
30279
30340
|
async function resolveTranscriptPath(session) {
|
|
30280
30341
|
if (session.transcriptPath) return session.transcriptPath;
|
|
@@ -30290,11 +30351,14 @@ async function reconcileTranscriptStatus(session, onStatusChange) {
|
|
|
30290
30351
|
const filePath = await resolveTranscriptPath(session);
|
|
30291
30352
|
if (!filePath) return;
|
|
30292
30353
|
const entries = await readTranscriptTail(filePath);
|
|
30354
|
+
const fingerprint = transcriptTailFingerprint(entries);
|
|
30355
|
+
if (fingerprint !== null && fingerprint === session.transcriptFingerprint)
|
|
30356
|
+
return;
|
|
30357
|
+
session.transcriptFingerprint = fingerprint ?? void 0;
|
|
30293
30358
|
const derived = deriveTranscriptStatus(entries, {
|
|
30294
30359
|
permissionActive: session.permissionActive
|
|
30295
30360
|
});
|
|
30296
30361
|
if (!derived) return;
|
|
30297
|
-
if (derived === "running") session.permissionActive = false;
|
|
30298
30362
|
if (derived === session.status) return;
|
|
30299
30363
|
daemonLog(
|
|
30300
30364
|
`session ${session.id} transcript reconcile: ${session.status} -> ${derived}`
|
|
@@ -30347,6 +30411,7 @@ function watchTranscript(session, notify2, onStatusChange) {
|
|
|
30347
30411
|
session.transcriptWatcher = void 0;
|
|
30348
30412
|
}
|
|
30349
30413
|
session.transcriptPath = void 0;
|
|
30414
|
+
session.transcriptFingerprint = void 0;
|
|
30350
30415
|
const fileName = `${session.claudeSessionId}.jsonl`;
|
|
30351
30416
|
let timer = null;
|
|
30352
30417
|
const run4 = () => {
|