@staff0rd/assist 0.962.0 → 0.964.0
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 +19 -17
- package/claude/commands/miro.md +1 -1
- package/claude/commands/releases-configure.md +3 -3
- package/claude/commands/review-config.md +3 -3
- package/dist/commands/sessions/web/bundle.js +521 -521
- package/dist/index.js +330 -236
- 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.
|
|
9
|
+
version: "0.964.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -6207,7 +6207,7 @@ var adviceConfigHelp = [
|
|
|
6207
6207
|
{
|
|
6208
6208
|
key: "advice.rules",
|
|
6209
6209
|
setter: "assist rules add '<text>' --title '<title>' --user",
|
|
6210
|
-
note: `listed under "Your rules"; user (db), user (node) and repo entries are concatenated in that order. --node writes ~/.assist.yml instead; 'assist config import-user' moves those into user (db)`
|
|
6210
|
+
note: `listed under "Your rules"; user (db), user (node), repo (db) and repo (git) entries are concatenated in that order. --node writes ~/.assist.yml instead; 'assist config import-user' moves those into user (db)`
|
|
6211
6211
|
}
|
|
6212
6212
|
];
|
|
6213
6213
|
|
|
@@ -6215,7 +6215,7 @@ var adviceConfigHelp = [
|
|
|
6215
6215
|
var askQuestionConfigHelp = [
|
|
6216
6216
|
{
|
|
6217
6217
|
key: "sessions.askQuestion",
|
|
6218
|
-
setter: "assist config set sessions.askQuestion true
|
|
6218
|
+
setter: "assist config set sessions.askQuestion true --node",
|
|
6219
6219
|
note: "opt in: assist ask-question answers AskUserQuestion questions from the session's web preview pane; when on, assist cli-hook denies AskUserQuestion in assist sessions and an advice fragment points Claude at assist ask-question; when off it exits non-zero so Claude uses the built-in tool (default off)"
|
|
6220
6220
|
}
|
|
6221
6221
|
];
|
|
@@ -6276,7 +6276,7 @@ var backupConfigHelp = [
|
|
|
6276
6276
|
var autoUpdateConfigHelp = [
|
|
6277
6277
|
{
|
|
6278
6278
|
key: "autoUpdate.enabled",
|
|
6279
|
-
setter: "assist config set autoUpdate.enabled false
|
|
6279
|
+
setter: "assist config set autoUpdate.enabled false --node",
|
|
6280
6280
|
note: "when this install is a git clone, the daemon pulls and builds it in the background as origin moves (assist watch wait --pull --build), logging each lap to ~/.assist/watchers/; a branch that cannot fast-forward starts a claude session to reconcile it and the loop resumes once it closes. Set false to stop it (default on)"
|
|
6281
6281
|
}
|
|
6282
6282
|
];
|
|
@@ -6317,8 +6317,8 @@ var complexityConfigHelp = [
|
|
|
6317
6317
|
var configConfigHelp = [
|
|
6318
6318
|
{
|
|
6319
6319
|
key: "repos",
|
|
6320
|
-
setter: "assist config set worktree.enabled true
|
|
6321
|
-
note: "per-repo overrides stored in the shared db, keyed by repo identity and seen by every node that uses it; written by 'config set
|
|
6320
|
+
setter: "assist config set worktree.enabled true --repo",
|
|
6321
|
+
note: "repo (db): per-repo overrides stored in the shared db, keyed by repo identity and seen by every node that uses it; written by 'config set --repo [name]' or the web /config repo (db) scope, and a yml repos: entry applies only until 'config import-repos' moves it"
|
|
6322
6322
|
}
|
|
6323
6323
|
];
|
|
6324
6324
|
|
|
@@ -6418,32 +6418,32 @@ var newsConfigHelp = [
|
|
|
6418
6418
|
var nextConfigHelp = [
|
|
6419
6419
|
{
|
|
6420
6420
|
key: "next.peers",
|
|
6421
|
-
setter: "assist config set next.peers alice,bob
|
|
6421
|
+
setter: "assist config set next.peers alice,bob --repo",
|
|
6422
6422
|
note: "GitHub logins whose open, non-draft PRs the web /next view lists for review alongside PRs requesting your review; PRs you approved with no newer commits are hidden"
|
|
6423
6423
|
},
|
|
6424
6424
|
{
|
|
6425
6425
|
key: "next.repos",
|
|
6426
|
-
setter: "assist config set next.repos my-org,other/web
|
|
6426
|
+
setter: "assist config set next.repos my-org,other/web --repo",
|
|
6427
6427
|
note: "GitHub repos the web /next view reads peer PRs and issues assigned to you from: owner/name for one repo, or a bare owner (org or user) for all its unarchived repos (default: the selected repo)"
|
|
6428
6428
|
},
|
|
6429
6429
|
{
|
|
6430
6430
|
key: "next.projects",
|
|
6431
|
-
setter: "assist config set next.projects my-org/3,my-org/5
|
|
6431
|
+
setter: "assist config set next.projects my-org/3,my-org/5 --repo",
|
|
6432
6432
|
note: "GitHub Projects (owner/number, from each URL) the web /next view suggests unassigned issues to pick up from; needs the gh project scope"
|
|
6433
6433
|
},
|
|
6434
6434
|
{
|
|
6435
6435
|
key: "next.pickStatuses",
|
|
6436
|
-
setter: "assist config set next.pickStatuses Ready,Todo
|
|
6436
|
+
setter: "assist config set next.pickStatuses Ready,Todo --repo",
|
|
6437
6437
|
note: "Project Status values whose unassigned items the web /next view offers to pick up (default: Ready, Todo)"
|
|
6438
6438
|
},
|
|
6439
6439
|
{
|
|
6440
6440
|
key: "next.excludeLabels",
|
|
6441
|
-
setter: "assist config set next.excludeLabels blocked,spike
|
|
6441
|
+
setter: "assist config set next.excludeLabels blocked,spike --repo",
|
|
6442
6442
|
note: "Labels whose project items the web /next view never offers to pick up (case-insensitive)"
|
|
6443
6443
|
},
|
|
6444
6444
|
{
|
|
6445
6445
|
key: "next.excludeTypes",
|
|
6446
|
-
setter: "assist config set next.excludeTypes Epic
|
|
6446
|
+
setter: "assist config set next.excludeTypes Epic --repo",
|
|
6447
6447
|
note: "GitHub issue types whose project items the web /next view never offers to pick up (case-insensitive)"
|
|
6448
6448
|
}
|
|
6449
6449
|
];
|
|
@@ -6577,7 +6577,7 @@ var reviewConfigHelp = [
|
|
|
6577
6577
|
|
|
6578
6578
|
// src/commands/sync/printAutoConfirmHint.ts
|
|
6579
6579
|
import chalk8 from "chalk";
|
|
6580
|
-
var autoConfirmHintCommand = "assist config set sync.autoConfirm true --
|
|
6580
|
+
var autoConfirmHintCommand = "assist config set sync.autoConfirm true --node";
|
|
6581
6581
|
function printAutoConfirmHint() {
|
|
6582
6582
|
console.log(
|
|
6583
6583
|
chalk8.dim(
|
|
@@ -6666,7 +6666,7 @@ var nodesConfigHelp = [
|
|
|
6666
6666
|
},
|
|
6667
6667
|
{
|
|
6668
6668
|
key: "sessions.linkVersionCheck",
|
|
6669
|
-
setter: "assist config set sessions.linkVersionCheck block
|
|
6669
|
+
setter: "assist config set sessions.linkVersionCheck block --node",
|
|
6670
6670
|
note: "reaction when a linked node's protocol range doesn't overlap this node's (app versions may differ; never restarts a peer): block (default) holds the link version-blocked until the older node is updated, warn proceeds, off skips the check"
|
|
6671
6671
|
}
|
|
6672
6672
|
];
|
|
@@ -6716,7 +6716,7 @@ var EXAMPLES = {
|
|
|
6716
6716
|
};
|
|
6717
6717
|
var hotkeysConfigHelp = Object.keys(ACTIONS).map((name) => ({
|
|
6718
6718
|
key: `sessions.hotkeys.${name}`,
|
|
6719
|
-
setter: `assist config set sessions.hotkeys.${name} ${EXAMPLES[name] ?? defaultHotkeys[name][0]}
|
|
6719
|
+
setter: `assist config set sessions.hotkeys.${name} ${EXAMPLES[name] ?? defaultHotkeys[name][0]} --node`,
|
|
6720
6720
|
note: `${ACTIONS[name]}; default ${defaultHotkeys[name].join(" / ")}`
|
|
6721
6721
|
}));
|
|
6722
6722
|
|
|
@@ -6724,52 +6724,52 @@ var hotkeysConfigHelp = Object.keys(ACTIONS).map((name) => ({
|
|
|
6724
6724
|
var sessionsConfigHelp = [
|
|
6725
6725
|
{
|
|
6726
6726
|
key: "sessions.nodeName",
|
|
6727
|
-
setter: "assist config set sessions.nodeName <name>
|
|
6727
|
+
setter: "assist config set sessions.nodeName <name> --node",
|
|
6728
6728
|
note: "this install's node label, shown in the web UI hamburger menu and reported by /api/health (default: OS hostname, with -wsl under WSL)"
|
|
6729
6729
|
},
|
|
6730
6730
|
{
|
|
6731
6731
|
key: "sessions.includeCommittedChanges",
|
|
6732
|
-
setter: "assist config set sessions.includeCommittedChanges false
|
|
6732
|
+
setter: "assist config set sessions.includeCommittedChanges false --node",
|
|
6733
6733
|
note: "default on: session card counts, /diff and the diff scope picker span the commits recorded against the session's backlog item as well as uncommitted work, so they survive the agent committing. Set false to show only uncommitted changes"
|
|
6734
6734
|
},
|
|
6735
6735
|
{
|
|
6736
6736
|
key: "sessions.maxLive",
|
|
6737
|
-
setter: "assist config set sessions.maxLive 24
|
|
6737
|
+
setter: "assist config set sessions.maxLive 24 --node",
|
|
6738
6738
|
note: "ceiling on concurrent live sessions one daemon holds; spawning past it is refused, and restore respawns at most this many persisted sessions (default: 24)"
|
|
6739
6739
|
},
|
|
6740
6740
|
{
|
|
6741
6741
|
key: "sessions.newSessionMode",
|
|
6742
|
-
setter: "assist config set sessions.newSessionMode bug
|
|
6742
|
+
setter: "assist config set sessions.newSessionMode bug --node",
|
|
6743
6743
|
note: "default mode pre-selected in the Ctrl+N new session dialog: draft | bug | prompt | design (default: draft)"
|
|
6744
6744
|
},
|
|
6745
6745
|
{
|
|
6746
6746
|
key: "worktree.enabled",
|
|
6747
|
-
setter: "assist config set worktree.enabled true
|
|
6747
|
+
setter: "assist config set worktree.enabled true --repo",
|
|
6748
6748
|
note: "opt in per repo: every session spills into a fresh adjacent <clone>-N worktree and the clone itself is never allocated; only inPlace launches (e.g. PR Review) and agents joining a stream stay in their tree (default off)"
|
|
6749
6749
|
},
|
|
6750
6750
|
{
|
|
6751
6751
|
key: "worktree.trunk",
|
|
6752
|
-
setter: "assist config set worktree.trunk true
|
|
6752
|
+
setter: "assist config set worktree.trunk true --repo",
|
|
6753
6753
|
note: "trunk-based: a worktree's branch tracks origin/<the clone's branch> so commits land on the mainline (default off: a worktree starts off the remote default with no mainline tracking, so the session raises its own branch and PR)"
|
|
6754
6754
|
},
|
|
6755
6755
|
{
|
|
6756
6756
|
key: "worktree.root",
|
|
6757
|
-
setter: "assist config set worktree.root ~/git
|
|
6757
|
+
setter: "assist config set worktree.root ~/git --repo",
|
|
6758
6758
|
note: "optional; parent dir for <clone>-N worktrees (default: the clone's parent)"
|
|
6759
6759
|
},
|
|
6760
6760
|
{
|
|
6761
6761
|
key: "worktree.install",
|
|
6762
|
-
setter: "assist config set worktree.install true
|
|
6762
|
+
setter: "assist config set worktree.install true --repo",
|
|
6763
6763
|
note: `per-worktree dep install: true auto-detects the package manager (npm ci when a package-lock.json exists), or give an explicit command; false to skip; or a JSON list of paths (e.g. '[".","packages/ui"]') to auto-detect and install in each, in order, stopping at the first failure`
|
|
6764
6764
|
},
|
|
6765
6765
|
{
|
|
6766
6766
|
key: "worktree.commitBeforePhaseEnd",
|
|
6767
|
-
setter: "assist config set worktree.commitBeforePhaseEnd true
|
|
6767
|
+
setter: "assist config set worktree.commitBeforePhaseEnd true --repo",
|
|
6768
6768
|
note: "phase prompts run /commit once verify passes \u2014 before asking the user to perform manual checks, or before phase-done when the phase has none \u2014 so work is not left uncommitted in a reapable worktree (default off)"
|
|
6769
6769
|
},
|
|
6770
6770
|
{
|
|
6771
6771
|
key: "worktree.copy",
|
|
6772
|
-
setter: "assist config set worktree.copy .env,.claude/settings.local.json
|
|
6772
|
+
setter: "assist config set worktree.copy .env,.claude/settings.local.json --repo",
|
|
6773
6773
|
note: "gitignored files copied into a new worktree so it can build/run"
|
|
6774
6774
|
}
|
|
6775
6775
|
];
|
|
@@ -6778,12 +6778,12 @@ var sessionsConfigHelp = [
|
|
|
6778
6778
|
var webConfigHelp = [
|
|
6779
6779
|
{
|
|
6780
6780
|
key: "sessions.tailscaleServe",
|
|
6781
|
-
setter: "assist config set sessions.tailscaleServe false
|
|
6781
|
+
setter: "assist config set sessions.tailscaleServe false --node",
|
|
6782
6782
|
note: "default on: the web server exposes its port on the tailnet with tailscale serve when it starts, so other nodes can link it by Tailscale name; set false to keep it off the tailnet"
|
|
6783
6783
|
},
|
|
6784
6784
|
{
|
|
6785
6785
|
key: "extension.redirects",
|
|
6786
|
-
setter: "assist config set extension.redirects.<owner>/<repo> <owner>/<repo>
|
|
6786
|
+
setter: "assist config set extension.redirects.<owner>/<repo> <owner>/<repo> --node",
|
|
6787
6787
|
note: "maps a GitHub owner/repo to the owner/repo whose clone under clone.baseDir hosts the browser extension's issue sessions; the prompt keeps the original link, and PR review sends are not redirected"
|
|
6788
6788
|
}
|
|
6789
6789
|
];
|
|
@@ -6907,6 +6907,20 @@ function isGlobalOnlyConfigKey(key) {
|
|
|
6907
6907
|
return GLOBAL_ONLY_KEYS.some((k) => key.startsWith(k));
|
|
6908
6908
|
}
|
|
6909
6909
|
|
|
6910
|
+
// src/commands/config/isNodeOnlyConfigKey.ts
|
|
6911
|
+
var DB_EXCLUDED_ROOTS = ["repos", "database"];
|
|
6912
|
+
function isNodeOnlyConfigKey(key) {
|
|
6913
|
+
const root2 = key.split(".")[0];
|
|
6914
|
+
return isGlobalOnlyConfigKey(key) || DB_EXCLUDED_ROOTS.includes(root2);
|
|
6915
|
+
}
|
|
6916
|
+
|
|
6917
|
+
// src/commands/config/configWritableScopes.ts
|
|
6918
|
+
function configWritableScopes(key) {
|
|
6919
|
+
if (isGlobalOnlyConfigKey(key)) return ["global"];
|
|
6920
|
+
if (isNodeOnlyConfigKey(key)) return ["project", "repo", "global"];
|
|
6921
|
+
return void 0;
|
|
6922
|
+
}
|
|
6923
|
+
|
|
6910
6924
|
// src/commands/config/resolveConfigSources.ts
|
|
6911
6925
|
function resolveConfigSources(key, layers) {
|
|
6912
6926
|
const sources = [];
|
|
@@ -6924,6 +6938,7 @@ function configEntryFor(leaf, { config, layers, globalConfigFile, schema: schema
|
|
|
6924
6938
|
const sources = resolveConfigSources(leaf.key, layers);
|
|
6925
6939
|
const node = configEntryNode(schema2, leaf.key);
|
|
6926
6940
|
const help = configHelpForKey(leaf.key);
|
|
6941
|
+
const writableScopes = configWritableScopes(leaf.key);
|
|
6927
6942
|
return {
|
|
6928
6943
|
...leaf,
|
|
6929
6944
|
...help ? { note: help.note, setter: help.setter } : {},
|
|
@@ -6935,7 +6950,7 @@ function configEntryFor(leaf, { config, layers, globalConfigFile, schema: schema
|
|
|
6935
6950
|
...layers.repoKey ? { repoKey: layers.repoKey } : {},
|
|
6936
6951
|
...layers.repoSource ? { repoSource: layers.repoSource } : {},
|
|
6937
6952
|
globalConfigFile,
|
|
6938
|
-
|
|
6953
|
+
...writableScopes ? { writableScopes } : {},
|
|
6939
6954
|
node
|
|
6940
6955
|
};
|
|
6941
6956
|
}
|
|
@@ -6977,7 +6992,7 @@ function isDbBackedConfigKey(key) {
|
|
|
6977
6992
|
return Object.hasOwn(dbBackedConfigKeys, key);
|
|
6978
6993
|
}
|
|
6979
6994
|
function dbBackedRepoError(key) {
|
|
6980
|
-
return `"${key}" is stored in
|
|
6995
|
+
return `"${key}" is stored in user (db) and shared by every repo; drop --repo`;
|
|
6981
6996
|
}
|
|
6982
6997
|
|
|
6983
6998
|
// src/commands/config/setNestedValue.ts
|
|
@@ -7048,17 +7063,15 @@ async function withDbBackedConfigValues(config, keys) {
|
|
|
7048
7063
|
}
|
|
7049
7064
|
|
|
7050
7065
|
// src/commands/config/withDbBackedConfigEntries.ts
|
|
7051
|
-
var DB_BACKED_CONFIG_FILE = "the shared db (all nodes)";
|
|
7052
7066
|
function dbBackedEntry(entry, value) {
|
|
7053
7067
|
const set = value !== void 0;
|
|
7054
7068
|
return {
|
|
7055
7069
|
...entry,
|
|
7056
7070
|
value: set ? value : entry.defaultValue,
|
|
7057
|
-
source: set ? "
|
|
7058
|
-
sources: set ? ["
|
|
7059
|
-
layers: set ? {
|
|
7060
|
-
|
|
7061
|
-
globalOnly: true
|
|
7071
|
+
source: set ? "user" : "default",
|
|
7072
|
+
sources: set ? ["user"] : [],
|
|
7073
|
+
layers: set ? { user: value } : {},
|
|
7074
|
+
writableScopes: ["user"]
|
|
7062
7075
|
};
|
|
7063
7076
|
}
|
|
7064
7077
|
async function withDbBackedConfigEntries(entries) {
|
|
@@ -10969,25 +10982,31 @@ async function nodeDoctor(req, res) {
|
|
|
10969
10982
|
respondJson(res, 200, { hop: await firstBrokenHop(link3) ?? null });
|
|
10970
10983
|
}
|
|
10971
10984
|
|
|
10985
|
+
// src/commands/config/configScopeNames.ts
|
|
10986
|
+
var configScopeNames = {
|
|
10987
|
+
project: "repo (git)",
|
|
10988
|
+
repo: "repo (db)",
|
|
10989
|
+
global: "user (node)",
|
|
10990
|
+
user: "user (db)"
|
|
10991
|
+
};
|
|
10992
|
+
|
|
10972
10993
|
// src/commands/config/applyDbBackedConfigWrite.ts
|
|
10973
10994
|
async function applyDbBackedConfigWrite(key, scope, write) {
|
|
10974
|
-
|
|
10995
|
+
const target = configScopeNames.user;
|
|
10996
|
+
if (scope !== "user")
|
|
10975
10997
|
return {
|
|
10976
10998
|
ok: false,
|
|
10977
|
-
errors: [`"${key}" is stored in
|
|
10999
|
+
errors: [`"${key}" is stored in ${target}; save it there`]
|
|
10978
11000
|
};
|
|
10979
11001
|
const handler = dbBackedConfigKeys[key];
|
|
10980
11002
|
const db = await getDb();
|
|
10981
11003
|
if ("unset" in write)
|
|
10982
11004
|
return {
|
|
10983
11005
|
ok: true,
|
|
10984
|
-
payload: {
|
|
10985
|
-
target: DB_BACKED_CONFIG_FILE,
|
|
10986
|
-
removed: await handler.unset(db)
|
|
10987
|
-
}
|
|
11006
|
+
payload: { target, removed: await handler.unset(db) }
|
|
10988
11007
|
};
|
|
10989
11008
|
await handler.write(db, write.value);
|
|
10990
|
-
return { ok: true, payload: { target
|
|
11009
|
+
return { ok: true, payload: { target } };
|
|
10991
11010
|
}
|
|
10992
11011
|
|
|
10993
11012
|
// src/commands/config/coerceConfigScalar.ts
|
|
@@ -11213,7 +11232,7 @@ function applyConfigSet(key, coerced, global, cwd = process.cwd(), globalConfigP
|
|
|
11213
11232
|
return {
|
|
11214
11233
|
ok: false,
|
|
11215
11234
|
errors: [
|
|
11216
|
-
`"${key}" is a
|
|
11235
|
+
`"${key}" is a user (node)-only key. Use --node to set it in ~/.assist.yml`
|
|
11217
11236
|
]
|
|
11218
11237
|
};
|
|
11219
11238
|
}
|
|
@@ -11235,7 +11254,7 @@ function globalOnlyRepoKeyError(key, verb) {
|
|
|
11235
11254
|
return {
|
|
11236
11255
|
ok: false,
|
|
11237
11256
|
errors: [
|
|
11238
|
-
`"${key}" is a
|
|
11257
|
+
`"${key}" is a user (node)-only key. ${verb} it in ~/.assist.yml with --node rather than in repo (db)`
|
|
11239
11258
|
]
|
|
11240
11259
|
};
|
|
11241
11260
|
}
|
|
@@ -11342,10 +11361,10 @@ async function applySharedRepoConfigSet(key, coerced, repoName, cwd = process.cw
|
|
|
11342
11361
|
|
|
11343
11362
|
// src/shared/db/updateUserConfig.ts
|
|
11344
11363
|
import { eq as eq24 } from "drizzle-orm";
|
|
11345
|
-
async function updateUserConfig(orm,
|
|
11364
|
+
async function updateUserConfig(orm, update4) {
|
|
11346
11365
|
return orm.transaction(async (tx) => {
|
|
11347
11366
|
const [row3] = await tx.select().from(userConfig).where(eq24(userConfig.id, 1)).for("update");
|
|
11348
|
-
const outcome =
|
|
11367
|
+
const outcome = update4(row3?.config ?? {});
|
|
11349
11368
|
if (!outcome.ok) return outcome;
|
|
11350
11369
|
if (Object.keys(outcome.config).length === 0) {
|
|
11351
11370
|
await tx.delete(userConfig).where(eq24(userConfig.id, 1));
|
|
@@ -11360,17 +11379,12 @@ async function updateUserConfig(orm, update3) {
|
|
|
11360
11379
|
}
|
|
11361
11380
|
|
|
11362
11381
|
// src/commands/config/userDbKeyError.ts
|
|
11363
|
-
var DB_EXCLUDED_ROOTS = ["repos", "database"];
|
|
11364
|
-
function isNodeOnlyKey(key) {
|
|
11365
|
-
const root2 = key.split(".")[0];
|
|
11366
|
-
return isGlobalOnlyConfigKey(key) || DB_EXCLUDED_ROOTS.includes(root2);
|
|
11367
|
-
}
|
|
11368
11382
|
function userDbKeyError(key, verb) {
|
|
11369
|
-
if (!
|
|
11383
|
+
if (!isNodeOnlyConfigKey(key)) return void 0;
|
|
11370
11384
|
return {
|
|
11371
11385
|
ok: false,
|
|
11372
11386
|
errors: [
|
|
11373
|
-
`"${key}" can't be stored in user (db); it stays in user (node). ${verb} it in ~/.assist.yml with
|
|
11387
|
+
`"${key}" can't be stored in user (db); it stays in user (node). ${verb} it in ~/.assist.yml with --node`
|
|
11374
11388
|
]
|
|
11375
11389
|
};
|
|
11376
11390
|
}
|
|
@@ -11430,7 +11444,10 @@ async function parseConfigWriteRequest(req) {
|
|
|
11430
11444
|
if (typeof cwd !== "string" || cwd === "")
|
|
11431
11445
|
return { ok: false, error: "Missing cwd" };
|
|
11432
11446
|
if (!isConfigWriteScope(scope))
|
|
11433
|
-
return {
|
|
11447
|
+
return {
|
|
11448
|
+
ok: false,
|
|
11449
|
+
error: 'scope must be "project", "repo", "global" or "user"'
|
|
11450
|
+
};
|
|
11434
11451
|
return { ok: true, key, value: body.value, cwd, scope };
|
|
11435
11452
|
}
|
|
11436
11453
|
|
|
@@ -11564,7 +11581,7 @@ function applyConfigUnset(key, global, cwd = process.cwd(), globalConfigPath) {
|
|
|
11564
11581
|
return {
|
|
11565
11582
|
ok: false,
|
|
11566
11583
|
errors: [
|
|
11567
|
-
`"${key}" is a
|
|
11584
|
+
`"${key}" is a user (node)-only key. Use --node to unset it in ~/.assist.yml`
|
|
11568
11585
|
]
|
|
11569
11586
|
};
|
|
11570
11587
|
}
|
|
@@ -21477,7 +21494,7 @@ function loadDenyConfig(global) {
|
|
|
21477
21494
|
|
|
21478
21495
|
// src/commands/deny/denyAdd.ts
|
|
21479
21496
|
function denyAdd(pattern2, message3, options2) {
|
|
21480
|
-
const { deny, saveDeny } = loadDenyConfig(options2.
|
|
21497
|
+
const { deny, saveDeny } = loadDenyConfig(options2.node);
|
|
21481
21498
|
if (deny.some((r) => r.pattern === pattern2)) {
|
|
21482
21499
|
console.log(chalk112.yellow(`Deny rule already exists for: ${pattern2}`));
|
|
21483
21500
|
return;
|
|
@@ -21515,7 +21532,7 @@ function denyList() {
|
|
|
21515
21532
|
// src/commands/deny/denyRemove.ts
|
|
21516
21533
|
import chalk114 from "chalk";
|
|
21517
21534
|
function denyRemove(pattern2, options2) {
|
|
21518
|
-
const { deny, saveDeny } = loadDenyConfig(options2.
|
|
21535
|
+
const { deny, saveDeny } = loadDenyConfig(options2.node);
|
|
21519
21536
|
const index2 = deny.findIndex((r) => r.pattern === pattern2);
|
|
21520
21537
|
if (index2 === -1) {
|
|
21521
21538
|
console.log(chalk114.yellow(`No deny rule found for: ${pattern2}`));
|
|
@@ -21530,8 +21547,8 @@ function denyRemove(pattern2, options2) {
|
|
|
21530
21547
|
function registerDeny(parent) {
|
|
21531
21548
|
const denyCommand = parent.command("deny").description("Manage command deny rules").action(denyList);
|
|
21532
21549
|
configHelp(denyCommand, denyConfigHelp);
|
|
21533
|
-
denyCommand.command("add").description("Add a deny rule for a command pattern").argument("<pattern>", "Command prefix to deny").argument("<message>", "Correction message shown to the agent").option("
|
|
21534
|
-
denyCommand.command("remove").description("Remove a deny rule by pattern").argument("<pattern>", "Command prefix to remove").option("
|
|
21550
|
+
denyCommand.command("add").description("Add a deny rule for a command pattern").argument("<pattern>", "Command prefix to deny").argument("<message>", "Correction message shown to the agent").option("--node", "Write to user (node): this node's ~/.assist.yml").action(denyAdd);
|
|
21551
|
+
denyCommand.command("remove").description("Remove a deny rule by pattern").argument("<pattern>", "Command prefix to remove").option("--node", "Remove from user (node): this node's ~/.assist.yml").action(denyRemove);
|
|
21535
21552
|
denyCommand.command("list").description("List all deny rules").action(denyList);
|
|
21536
21553
|
}
|
|
21537
21554
|
|
|
@@ -23427,25 +23444,25 @@ import chalk136 from "chalk";
|
|
|
23427
23444
|
async function setDbBackedConfigKey(key, value, useRepo) {
|
|
23428
23445
|
if (useRepo) exitWithConfigErrors([dbBackedRepoError(key)]);
|
|
23429
23446
|
await dbBackedConfigKeys[key].write(await getDb(), value);
|
|
23430
|
-
console.log(chalk136.green(`Set ${key} = ${JSON.stringify(value)} (
|
|
23447
|
+
console.log(chalk136.green(`Set ${key} = ${JSON.stringify(value)} (user (db))`));
|
|
23431
23448
|
}
|
|
23432
23449
|
|
|
23433
23450
|
// src/commands/config/setFileConfigKey.ts
|
|
23434
23451
|
import chalk137 from "chalk";
|
|
23435
|
-
async function setFileConfigKey({ key, useRepo, repoName,
|
|
23436
|
-
const target = useRepo ?
|
|
23452
|
+
async function setFileConfigKey({ key, useRepo, repoName, node, user }, coerced) {
|
|
23453
|
+
const target = useRepo ? `${configScopeNames.repo}: ${await applyRepoOrExit(key, coerced, repoName)}` : user ? await applyUserOrExit(key, coerced) : applyOrExit(key, coerced, node);
|
|
23437
23454
|
const shown = JSON.stringify(maskConfigKeySecrets(key, coerced));
|
|
23438
23455
|
console.log(chalk137.green(`Set ${key} = ${shown} (${target})`));
|
|
23439
23456
|
}
|
|
23440
|
-
function applyOrExit(key, coerced,
|
|
23441
|
-
const result = applyConfigSet(key, coerced,
|
|
23457
|
+
function applyOrExit(key, coerced, node) {
|
|
23458
|
+
const result = applyConfigSet(key, coerced, node);
|
|
23442
23459
|
if (!result.ok) exitWithConfigErrors(result.errors);
|
|
23443
|
-
return result.target;
|
|
23460
|
+
return configScopeNames[result.target];
|
|
23444
23461
|
}
|
|
23445
23462
|
async function applyUserOrExit(key, coerced) {
|
|
23446
23463
|
const result = await applyUserConfigSet(key, coerced);
|
|
23447
23464
|
if (!result.ok) exitWithConfigErrors(result.errors);
|
|
23448
|
-
return
|
|
23465
|
+
return configScopeNames.user;
|
|
23449
23466
|
}
|
|
23450
23467
|
async function applyRepoOrExit(key, coerced, repoName) {
|
|
23451
23468
|
const result = await applySharedRepoConfigSet(key, coerced, repoName);
|
|
@@ -23454,17 +23471,20 @@ async function applyRepoOrExit(key, coerced, repoName) {
|
|
|
23454
23471
|
}
|
|
23455
23472
|
|
|
23456
23473
|
// src/commands/config/scopeOptionsError.ts
|
|
23457
|
-
function scopeOptionsError(options2
|
|
23458
|
-
|
|
23459
|
-
|
|
23460
|
-
|
|
23461
|
-
|
|
23474
|
+
function scopeOptionsError(options2) {
|
|
23475
|
+
const chosen = [
|
|
23476
|
+
options2.repo !== void 0 && "--repo",
|
|
23477
|
+
options2.node && "--node",
|
|
23478
|
+
options2.user && "--user"
|
|
23479
|
+
].filter(Boolean);
|
|
23480
|
+
if (chosen.length > 1)
|
|
23481
|
+
return `${chosen.join(" and ")} pick different scopes; pass one: --repo for repo (db), --node for user (node), --user for user (db)`;
|
|
23462
23482
|
return void 0;
|
|
23463
23483
|
}
|
|
23464
23484
|
|
|
23465
23485
|
// src/commands/config/configSet.ts
|
|
23466
23486
|
async function configSet(key, value, options2 = {}) {
|
|
23467
|
-
const scopeError = scopeOptionsError(options2
|
|
23487
|
+
const scopeError = scopeOptionsError(options2);
|
|
23468
23488
|
if (scopeError) exitWithConfigErrors([scopeError]);
|
|
23469
23489
|
const resolved = resolveRepoTarget(key, value, options2.repo);
|
|
23470
23490
|
if (resolved.value === void 0) {
|
|
@@ -23478,7 +23498,7 @@ async function configSet(key, value, options2 = {}) {
|
|
|
23478
23498
|
await setFileConfigKey(
|
|
23479
23499
|
{
|
|
23480
23500
|
...resolved,
|
|
23481
|
-
|
|
23501
|
+
node: options2.node ?? false,
|
|
23482
23502
|
user: options2.user ?? false
|
|
23483
23503
|
},
|
|
23484
23504
|
coercion.value
|
|
@@ -23504,7 +23524,7 @@ async function unsetDbBackedConfigKey(key, useRepo) {
|
|
|
23504
23524
|
if (useRepo) exitWithConfigErrors([dbBackedRepoError(key)]);
|
|
23505
23525
|
const removed = await dbBackedConfigKeys[key].unset(await getDb());
|
|
23506
23526
|
console.log(
|
|
23507
|
-
removed ? chalk139.green(`Unset ${key} (
|
|
23527
|
+
removed ? chalk139.green(`Unset ${key} (user (db))`) : chalk139.yellow(`${key} is not set in user (db)`)
|
|
23508
23528
|
);
|
|
23509
23529
|
}
|
|
23510
23530
|
|
|
@@ -23514,31 +23534,26 @@ async function unsetFileConfigKey({
|
|
|
23514
23534
|
key,
|
|
23515
23535
|
useRepo,
|
|
23516
23536
|
repoName,
|
|
23517
|
-
|
|
23537
|
+
node,
|
|
23518
23538
|
user
|
|
23519
23539
|
}) {
|
|
23520
|
-
const result = useRepo ? await applySharedRepoConfigUnset(key, repoName) : user ? await applyUserConfigUnset(key) : applyConfigUnset(key,
|
|
23540
|
+
const result = useRepo ? await applySharedRepoConfigUnset(key, repoName) : user ? await applyUserConfigUnset(key) : applyConfigUnset(key, node);
|
|
23521
23541
|
if (!result.ok) exitWithConfigErrors(result.errors);
|
|
23522
23542
|
if (!result.removed) {
|
|
23523
|
-
console.log(chalk140.yellow(`${key} is not set in ${
|
|
23543
|
+
console.log(chalk140.yellow(`${key} is not set in ${targetLabel(result)}`));
|
|
23524
23544
|
return;
|
|
23525
23545
|
}
|
|
23526
23546
|
console.log(chalk140.green(`Unset ${key} (${targetLabel(result)})`));
|
|
23527
23547
|
}
|
|
23528
|
-
function whereLabel(result) {
|
|
23529
|
-
if (result.target === "repo") return `repos.${result.label}`;
|
|
23530
|
-
if (result.target === "user") return "user (db)";
|
|
23531
|
-
return `the ${result.target} config`;
|
|
23532
|
-
}
|
|
23533
23548
|
function targetLabel(result) {
|
|
23534
|
-
if (result.target === "repo")
|
|
23535
|
-
|
|
23536
|
-
return result.target;
|
|
23549
|
+
if (result.target === "repo")
|
|
23550
|
+
return `${configScopeNames.repo}: ${result.label}`;
|
|
23551
|
+
return configScopeNames[result.target];
|
|
23537
23552
|
}
|
|
23538
23553
|
|
|
23539
23554
|
// src/commands/config/configUnset.ts
|
|
23540
23555
|
async function configUnset(key, options2 = {}) {
|
|
23541
|
-
const scopeError = scopeOptionsError(options2
|
|
23556
|
+
const scopeError = scopeOptionsError(options2);
|
|
23542
23557
|
if (scopeError) exitWithConfigErrors([scopeError]);
|
|
23543
23558
|
const resolved = resolveRepoUnsetTarget(key, options2.repo);
|
|
23544
23559
|
if (resolved.key === void 0) {
|
|
@@ -23552,24 +23567,28 @@ async function configUnset(key, options2 = {}) {
|
|
|
23552
23567
|
key: resolved.key,
|
|
23553
23568
|
useRepo: resolved.useRepo,
|
|
23554
23569
|
repoName: resolved.repoName,
|
|
23555
|
-
|
|
23570
|
+
node: options2.node ?? false,
|
|
23556
23571
|
user: options2.user ?? false
|
|
23557
23572
|
});
|
|
23558
23573
|
}
|
|
23559
23574
|
|
|
23560
23575
|
// src/commands/config/registerConfigWrites.ts
|
|
23561
23576
|
function registerConfigWrites(configCommand) {
|
|
23562
|
-
configCommand.command("set <key> [value]").description(
|
|
23563
|
-
"
|
|
23564
|
-
"Requires -g: write a repo's override to the shared db, seen by every node (defaults to the current repo)"
|
|
23577
|
+
configCommand.command("set <key> [value]").description(
|
|
23578
|
+
"Set a config value (e.g. commit.push true); with no scope flag it writes repo (git), this repo's assist.yml"
|
|
23565
23579
|
).option(
|
|
23580
|
+
"-r, --repo [name]",
|
|
23581
|
+
"Write to repo (db): a repo's override in the shared db, seen by every node (defaults to the current repo)"
|
|
23582
|
+
).option("--node", "Write to user (node): this node's ~/.assist.yml").option(
|
|
23566
23583
|
"-u, --user",
|
|
23567
23584
|
"Write to user (db): the shared db, applied to every repo on every node"
|
|
23568
23585
|
).action((key, value, options2) => configSet(key, value, options2));
|
|
23569
|
-
configCommand.command("unset [key]").description(
|
|
23586
|
+
configCommand.command("unset [key]").description(
|
|
23587
|
+
"Remove a config value (e.g. commit.push); with no scope flag it removes it from repo (git), this repo's assist.yml"
|
|
23588
|
+
).option(
|
|
23570
23589
|
"-r, --repo [name]",
|
|
23571
|
-
"
|
|
23572
|
-
).option("-u, --user", "Remove from user (db) in the shared db").action((key, options2) => configUnset(key, options2));
|
|
23590
|
+
"Remove from repo (db): a repo's override in the shared db (defaults to the current repo)"
|
|
23591
|
+
).option("--node", "Remove from user (node): this node's ~/.assist.yml").option("-u, --user", "Remove from user (db) in the shared db").action((key, options2) => configUnset(key, options2));
|
|
23573
23592
|
}
|
|
23574
23593
|
|
|
23575
23594
|
// src/commands/registerConfig.ts
|
|
@@ -26118,6 +26137,7 @@ function candidateStrings(input, existingContent) {
|
|
|
26118
26137
|
}
|
|
26119
26138
|
}
|
|
26120
26139
|
function decideOverrideGuard(input, existingContent) {
|
|
26140
|
+
if (/\.mdx?$/i.test(input.tool_input.file_path ?? "")) return void 0;
|
|
26121
26141
|
const touchesMarker = candidateStrings(input, existingContent).some(
|
|
26122
26142
|
(s) => s.includes(MAINTAINABILITY_OVERRIDE_MARKER)
|
|
26123
26143
|
);
|
|
@@ -29917,9 +29937,9 @@ async function saveMiroExtract(name, extract2, options2, paths = {}) {
|
|
|
29917
29937
|
cwd: paths.cwd ?? process.cwd(),
|
|
29918
29938
|
globalConfigPath: paths.globalConfigPath ?? getGlobalConfigPath()
|
|
29919
29939
|
};
|
|
29920
|
-
if (options2.repo !== void 0 &&
|
|
29940
|
+
if (options2.repo !== void 0 && options2.node)
|
|
29921
29941
|
throw new MiroExtractError(
|
|
29922
|
-
"--repo writes
|
|
29942
|
+
"--repo writes repo (db) and --node writes user (node); pass one"
|
|
29923
29943
|
);
|
|
29924
29944
|
const key = `miro.extracts.${name}`;
|
|
29925
29945
|
if (options2.repo !== void 0)
|
|
@@ -29927,7 +29947,7 @@ async function saveMiroExtract(name, extract2, options2, paths = {}) {
|
|
|
29927
29947
|
const result = applyConfigSet(
|
|
29928
29948
|
key,
|
|
29929
29949
|
extract2,
|
|
29930
|
-
options2.
|
|
29950
|
+
options2.node ?? false,
|
|
29931
29951
|
resolved.cwd,
|
|
29932
29952
|
resolved.globalConfigPath
|
|
29933
29953
|
);
|
|
@@ -30194,9 +30214,12 @@ function registerMiro(program) {
|
|
|
30194
30214
|
).option(
|
|
30195
30215
|
"--save <name>",
|
|
30196
30216
|
"Save the selection as this named extract without asking"
|
|
30197
|
-
).option(
|
|
30217
|
+
).option(
|
|
30218
|
+
"--node",
|
|
30219
|
+
"Save the extract to user (node), this node's ~/.assist.yml"
|
|
30220
|
+
).option(
|
|
30198
30221
|
"-r, --repo [name]",
|
|
30199
|
-
"
|
|
30222
|
+
"Save the extract to repo (db), a repo's shared db override (defaults to the current repo)"
|
|
30200
30223
|
).action(
|
|
30201
30224
|
(name, options2) => runExtract(name, options2)
|
|
30202
30225
|
);
|
|
@@ -30651,8 +30674,8 @@ function extractLinkedInPosts(flight, author = findAuthorSlug(flight)) {
|
|
|
30651
30674
|
}
|
|
30652
30675
|
|
|
30653
30676
|
// src/commands/netcap/collectVoyagerAttributes.ts
|
|
30654
|
-
function attributeDetails(
|
|
30655
|
-
const attrs = asObject(asObject(
|
|
30677
|
+
function attributeDetails(update4) {
|
|
30678
|
+
const attrs = asObject(asObject(update4.commentary)?.text)?.attributesV2;
|
|
30656
30679
|
if (!Array.isArray(attrs)) return [];
|
|
30657
30680
|
return attrs.map((a) => asObject(asObject(a)?.detailData)).filter((d) => d !== void 0);
|
|
30658
30681
|
}
|
|
@@ -30679,23 +30702,23 @@ function hashtagsFrom(details) {
|
|
|
30679
30702
|
function textLinksFrom(details) {
|
|
30680
30703
|
return details.map((detail) => asObject(detail.textLink)?.url).filter((url) => typeof url === "string");
|
|
30681
30704
|
}
|
|
30682
|
-
function articleCardLinksFrom(
|
|
30683
|
-
const article = asObject(asObject(
|
|
30705
|
+
function articleCardLinksFrom(update4) {
|
|
30706
|
+
const article = asObject(asObject(update4.content)?.articleComponent);
|
|
30684
30707
|
const url = asObject(article?.navigationContext)?.actionTarget;
|
|
30685
30708
|
return typeof url === "string" ? [url] : [];
|
|
30686
30709
|
}
|
|
30687
|
-
function linksFrom(
|
|
30710
|
+
function linksFrom(update4, details) {
|
|
30688
30711
|
return dedupeLinks([
|
|
30689
30712
|
...textLinksFrom(details),
|
|
30690
|
-
...articleCardLinksFrom(
|
|
30713
|
+
...articleCardLinksFrom(update4)
|
|
30691
30714
|
]);
|
|
30692
30715
|
}
|
|
30693
|
-
function collectVoyagerAttributes(
|
|
30694
|
-
const details = attributeDetails(
|
|
30716
|
+
function collectVoyagerAttributes(update4, profiles, authorSlug) {
|
|
30717
|
+
const details = attributeDetails(update4);
|
|
30695
30718
|
return {
|
|
30696
30719
|
mentions: mentionsFrom(details, profiles, authorSlug),
|
|
30697
30720
|
hashtags: hashtagsFrom(details),
|
|
30698
|
-
links: linksFrom(
|
|
30721
|
+
links: linksFrom(update4, details)
|
|
30699
30722
|
};
|
|
30700
30723
|
}
|
|
30701
30724
|
|
|
@@ -30706,8 +30729,8 @@ function profileSlug(actor) {
|
|
|
30706
30729
|
if (typeof target !== "string") return void 0;
|
|
30707
30730
|
return target.match(/\/in\/([^/?]+)/)?.[1];
|
|
30708
30731
|
}
|
|
30709
|
-
function resolveVoyagerAuthor(
|
|
30710
|
-
const actor = asObject(
|
|
30732
|
+
function resolveVoyagerAuthor(update4) {
|
|
30733
|
+
const actor = asObject(update4.actor);
|
|
30711
30734
|
const slug2 = profileSlug(actor);
|
|
30712
30735
|
if (!slug2) return void 0;
|
|
30713
30736
|
const name = asObject(actor?.name)?.text;
|
|
@@ -30717,24 +30740,24 @@ function resolveVoyagerAuthor(update3) {
|
|
|
30717
30740
|
}
|
|
30718
30741
|
|
|
30719
30742
|
// src/commands/netcap/buildVoyagerPost.ts
|
|
30720
|
-
function commentaryText(
|
|
30721
|
-
const body = asObject(asObject(
|
|
30743
|
+
function commentaryText(update4) {
|
|
30744
|
+
const body = asObject(asObject(update4.commentary)?.text)?.text;
|
|
30722
30745
|
return typeof body === "string" && body.trim() ? body.trim() : void 0;
|
|
30723
30746
|
}
|
|
30724
|
-
function activityUrnOf(
|
|
30725
|
-
const urn = asObject(
|
|
30747
|
+
function activityUrnOf(update4) {
|
|
30748
|
+
const urn = asObject(update4.metadata)?.backendUrn;
|
|
30726
30749
|
return typeof urn === "string" ? urn : void 0;
|
|
30727
30750
|
}
|
|
30728
|
-
function buildVoyagerPost(
|
|
30729
|
-
const text18 = commentaryText(
|
|
30751
|
+
function buildVoyagerPost(update4, profiles) {
|
|
30752
|
+
const text18 = commentaryText(update4);
|
|
30730
30753
|
if (!text18) return void 0;
|
|
30731
|
-
const author = resolveVoyagerAuthor(
|
|
30754
|
+
const author = resolveVoyagerAuthor(update4);
|
|
30732
30755
|
const { mentions, hashtags, links: links2 } = collectVoyagerAttributes(
|
|
30733
|
-
|
|
30756
|
+
update4,
|
|
30734
30757
|
profiles,
|
|
30735
30758
|
author?.slug
|
|
30736
30759
|
);
|
|
30737
|
-
const activityUrn = activityUrnOf(
|
|
30760
|
+
const activityUrn = activityUrnOf(update4);
|
|
30738
30761
|
return {
|
|
30739
30762
|
text: text18,
|
|
30740
30763
|
markdown: linkifyMentions(text18, mentions),
|
|
@@ -30802,9 +30825,9 @@ function extractVoyagerPosts(body) {
|
|
|
30802
30825
|
const profiles = voyagerProfileMentions(included);
|
|
30803
30826
|
const posts = [];
|
|
30804
30827
|
for (const ref of elementUrns(rootObj)) {
|
|
30805
|
-
const
|
|
30806
|
-
if (!
|
|
30807
|
-
const post2 = buildVoyagerPost(
|
|
30828
|
+
const update4 = byUrn.get(ref);
|
|
30829
|
+
if (!update4) continue;
|
|
30830
|
+
const post2 = buildVoyagerPost(update4, profiles);
|
|
30808
30831
|
if (post2) posts.push(post2);
|
|
30809
30832
|
}
|
|
30810
30833
|
return posts;
|
|
@@ -33863,6 +33886,15 @@ function registerRavendb(program) {
|
|
|
33863
33886
|
// src/commands/releases/releasesConfigure.ts
|
|
33864
33887
|
import chalk211 from "chalk";
|
|
33865
33888
|
|
|
33889
|
+
// src/commands/config/parseRepoScopeFlag.ts
|
|
33890
|
+
var REPO_SCOPE_FLAGS = {
|
|
33891
|
+
git: "project",
|
|
33892
|
+
db: "repo"
|
|
33893
|
+
};
|
|
33894
|
+
function parseRepoScopeFlag(value) {
|
|
33895
|
+
return value === void 0 ? void 0 : REPO_SCOPE_FLAGS[value];
|
|
33896
|
+
}
|
|
33897
|
+
|
|
33866
33898
|
// src/commands/releases/checkStreamGraph.ts
|
|
33867
33899
|
function nodeIds(stream) {
|
|
33868
33900
|
const nodes = Array.isArray(stream.nodes) ? stream.nodes : [];
|
|
@@ -33971,7 +34003,7 @@ async function writeConfigKeys(writes, scope, cwd = process.cwd()) {
|
|
|
33971
34003
|
return {
|
|
33972
34004
|
ok: false,
|
|
33973
34005
|
errors: globalOnly.map(
|
|
33974
|
-
(write) => `"${write.key}" is a
|
|
34006
|
+
(write) => `"${write.key}" is a user (node)-only key. Set it with 'assist config set ${write.key} <value> --node'`
|
|
33975
34007
|
)
|
|
33976
34008
|
};
|
|
33977
34009
|
}
|
|
@@ -33979,7 +34011,7 @@ async function writeConfigKeys(writes, scope, cwd = process.cwd()) {
|
|
|
33979
34011
|
const applied = applyConfigWrites(loadProjectConfig(cwd), writes);
|
|
33980
34012
|
if (!applied.ok) return applied;
|
|
33981
34013
|
saveConfig(applied.updated, cwd);
|
|
33982
|
-
return { ok: true, target: "
|
|
34014
|
+
return { ok: true, target: "repo (git), this repo's assist.yml" };
|
|
33983
34015
|
}
|
|
33984
34016
|
async function writeRepoBlock(writes, cwd) {
|
|
33985
34017
|
const orm = await getDb();
|
|
@@ -33987,7 +34019,10 @@ async function writeRepoBlock(writes, cwd) {
|
|
|
33987
34019
|
const applied = applyConfigWrites(block, writes, repoConfigSchema);
|
|
33988
34020
|
if (!applied.ok) return applied;
|
|
33989
34021
|
await saveSharedRepoBlock(orm, label, applied.updated);
|
|
33990
|
-
return {
|
|
34022
|
+
return {
|
|
34023
|
+
ok: true,
|
|
34024
|
+
target: `repo (db), ${SHARED_REPO_CONFIG_SOURCE}, repo: ${label}`
|
|
34025
|
+
};
|
|
33991
34026
|
}
|
|
33992
34027
|
|
|
33993
34028
|
// src/commands/releases/declaredStreamsInScope.ts
|
|
@@ -34043,7 +34078,8 @@ function reportWritten(incoming, target) {
|
|
|
34043
34078
|
);
|
|
34044
34079
|
}
|
|
34045
34080
|
async function releasesConfigure(options2 = {}) {
|
|
34046
|
-
const scope = options2.scope
|
|
34081
|
+
const scope = parseRepoScopeFlag(options2.scope ?? "git");
|
|
34082
|
+
if (!scope) return fail7("--scope must be 'git' or 'db'");
|
|
34047
34083
|
const input = readStreamsInput(options2.streams ?? "-");
|
|
34048
34084
|
if ("error" in input) return fail7(`Could not read --streams: ${input.error}`);
|
|
34049
34085
|
const incoming = withCurrentRepo(input.streams);
|
|
@@ -34102,9 +34138,9 @@ function registerReleases(parent) {
|
|
|
34102
34138
|
"--streams <file>",
|
|
34103
34139
|
"JSON or YAML array of streams to declare; '-' reads stdin"
|
|
34104
34140
|
).option(
|
|
34105
|
-
"--scope <
|
|
34106
|
-
"
|
|
34107
|
-
"
|
|
34141
|
+
"--scope <git|db>",
|
|
34142
|
+
"repo (git), the repo's assist.yml, or repo (db), this repo's shared db override",
|
|
34143
|
+
"git"
|
|
34108
34144
|
).action(releasesConfigure),
|
|
34109
34145
|
"/releases-configure"
|
|
34110
34146
|
);
|
|
@@ -37115,11 +37151,11 @@ async function promptConfigScope() {
|
|
|
37115
37151
|
choices: [
|
|
37116
37152
|
{
|
|
37117
37153
|
name: "repo",
|
|
37118
|
-
message: "this repo's override in the shared db \u2014 personal, seen by every node, as 'config set
|
|
37154
|
+
message: "repo (db): this repo's override in the shared db \u2014 personal, seen by every node, as 'config set --repo' writes it"
|
|
37119
37155
|
},
|
|
37120
37156
|
{
|
|
37121
37157
|
name: "project",
|
|
37122
|
-
message: "assist.yml in this repo \u2014 checked in, shared with the team"
|
|
37158
|
+
message: "repo (git): assist.yml in this repo \u2014 checked in, shared with the team"
|
|
37123
37159
|
}
|
|
37124
37160
|
]
|
|
37125
37161
|
}).run()
|
|
@@ -37388,7 +37424,7 @@ async function configureHighLevelReview(options2 = {}) {
|
|
|
37388
37424
|
},
|
|
37389
37425
|
proposed
|
|
37390
37426
|
);
|
|
37391
|
-
const scope =
|
|
37427
|
+
const scope = parseRepoScopeFlag(options2.scope);
|
|
37392
37428
|
reportConfigured(
|
|
37393
37429
|
await configureConfigKeys(questions, {
|
|
37394
37430
|
answers,
|
|
@@ -37396,10 +37432,6 @@ async function configureHighLevelReview(options2 = {}) {
|
|
|
37396
37432
|
})
|
|
37397
37433
|
);
|
|
37398
37434
|
}
|
|
37399
|
-
function asConfigKeyScope(value) {
|
|
37400
|
-
if (value === "project" || value === "repo") return value;
|
|
37401
|
-
return void 0;
|
|
37402
|
-
}
|
|
37403
37435
|
function reportConfigured(result) {
|
|
37404
37436
|
for (const write of result.written)
|
|
37405
37437
|
console.log(
|
|
@@ -37840,15 +37872,15 @@ function checkDescriptionSections(body) {
|
|
|
37840
37872
|
}
|
|
37841
37873
|
|
|
37842
37874
|
// src/commands/review/highLevel/checkDescriptionWordCap.ts
|
|
37843
|
-
function checkDescriptionWordCap(body,
|
|
37875
|
+
function checkDescriptionWordCap(body, cap3) {
|
|
37844
37876
|
const { prose, code } = countReadingWords(body);
|
|
37845
37877
|
const words = prose + code;
|
|
37846
|
-
if (words >
|
|
37878
|
+
if (words > cap3)
|
|
37847
37879
|
return {
|
|
37848
37880
|
status: "fail",
|
|
37849
|
-
reason: `${words} words, ${words -
|
|
37881
|
+
reason: `${words} words, ${words - cap3} over the ${cap3}-word cap`
|
|
37850
37882
|
};
|
|
37851
|
-
return { status: "pass", reason: `${words} of ${
|
|
37883
|
+
return { status: "pass", reason: `${words} of ${cap3} words` };
|
|
37852
37884
|
}
|
|
37853
37885
|
|
|
37854
37886
|
// src/commands/review/highLevel/checkNoMergeConflicts.ts
|
|
@@ -41050,8 +41082,8 @@ function validateConfigureOptions(options2) {
|
|
|
41050
41082
|
console.error("Error: --configure takes no PR number.");
|
|
41051
41083
|
process.exit(1);
|
|
41052
41084
|
}
|
|
41053
|
-
if (options2.scope && options2.scope
|
|
41054
|
-
console.error("Error: --scope must be '
|
|
41085
|
+
if (options2.scope && !parseRepoScopeFlag(options2.scope)) {
|
|
41086
|
+
console.error("Error: --scope must be 'git' or 'db'.");
|
|
41055
41087
|
process.exit(1);
|
|
41056
41088
|
}
|
|
41057
41089
|
}
|
|
@@ -41140,7 +41172,7 @@ function addReviewModeOptions(command) {
|
|
|
41140
41172
|
"With --high-level: review nothing and instead ask for review.highLevel.criticalPaths, uiPaths and descriptionWordCap one at a time, each prefilled with its current value or, when unset, globs Claude proposes from this repo's own tree (for criticalPaths, merged with its defaults), then write the answers in one pass to either this repo's override in the shared assist database or the project assist.yml. A blank answer leaves that key unset"
|
|
41141
41173
|
).option(
|
|
41142
41174
|
"--scope <scope>",
|
|
41143
|
-
"With --configure: write to '
|
|
41175
|
+
"With --configure: write to 'db' (repo (db), this repo's override in the shared assist database) or 'git' (repo (git), the repo's own assist.yml) instead of asking which"
|
|
41144
41176
|
).option(
|
|
41145
41177
|
"--answer <key=value>",
|
|
41146
41178
|
"With --configure: answer one key without prompting, for an agent that has already put the choice to the user (repeatable); an empty value leaves that key unset. Answer all three and nothing is prompted for and no globs are proposed",
|
|
@@ -45972,6 +46004,25 @@ function toSessionRunInfo({
|
|
|
45972
46004
|
};
|
|
45973
46005
|
}
|
|
45974
46006
|
|
|
46007
|
+
// src/commands/sessions/daemon/toSessionViewInfo.ts
|
|
46008
|
+
function toSessionViewInfo({
|
|
46009
|
+
lastUserMessage,
|
|
46010
|
+
lastAssistantMessage,
|
|
46011
|
+
cols,
|
|
46012
|
+
rows,
|
|
46013
|
+
activeViewer,
|
|
46014
|
+
activeViewerNode
|
|
46015
|
+
}) {
|
|
46016
|
+
return {
|
|
46017
|
+
lastUserMessage,
|
|
46018
|
+
lastAssistantMessage,
|
|
46019
|
+
cols,
|
|
46020
|
+
rows,
|
|
46021
|
+
activeViewer,
|
|
46022
|
+
activeViewerNode
|
|
46023
|
+
};
|
|
46024
|
+
}
|
|
46025
|
+
|
|
45975
46026
|
// src/commands/sessions/daemon/worktree/joinRefusal.ts
|
|
45976
46027
|
import { existsSync as existsSync85 } from "fs";
|
|
45977
46028
|
function joinRefusal(session) {
|
|
@@ -46006,13 +46057,11 @@ function toSessionInfo(session) {
|
|
|
46006
46057
|
seeding,
|
|
46007
46058
|
pendingPrPreview,
|
|
46008
46059
|
pendingShow,
|
|
46009
|
-
undurable
|
|
46010
|
-
lastUserMessage,
|
|
46011
|
-
activeViewer,
|
|
46012
|
-
activeViewerNode
|
|
46060
|
+
undurable
|
|
46013
46061
|
} = session;
|
|
46014
46062
|
return {
|
|
46015
46063
|
...toSessionRunInfo(session),
|
|
46064
|
+
...toSessionViewInfo(session),
|
|
46016
46065
|
id,
|
|
46017
46066
|
name,
|
|
46018
46067
|
title,
|
|
@@ -46035,9 +46084,6 @@ function toSessionInfo(session) {
|
|
|
46035
46084
|
pendingPrPreview,
|
|
46036
46085
|
pendingShow,
|
|
46037
46086
|
undurable,
|
|
46038
|
-
lastUserMessage,
|
|
46039
|
-
activeViewer,
|
|
46040
|
-
activeViewerNode,
|
|
46041
46087
|
promptIssue: promptIssueRef(session.initialPrompt),
|
|
46042
46088
|
promptPr: promptPrNumber(session.initialPrompt),
|
|
46043
46089
|
joinable: joinRefusal(session) === void 0
|
|
@@ -46550,10 +46596,13 @@ var SessionIo = class {
|
|
|
46550
46596
|
}
|
|
46551
46597
|
writeAsDaemon = (id, data) => this.write(id, data, {});
|
|
46552
46598
|
resize(id, cols, rows, viewer) {
|
|
46599
|
+
const s = this.sessions.get(id);
|
|
46600
|
+
const before = `${s?.cols}x${s?.rows}`;
|
|
46553
46601
|
resizeSession(this.sessions, id, cols, rows, {
|
|
46554
46602
|
...viewer,
|
|
46555
46603
|
onClaim: this.notify
|
|
46556
46604
|
});
|
|
46605
|
+
if (s && `${s.cols}x${s.rows}` !== before) this.notify();
|
|
46557
46606
|
}
|
|
46558
46607
|
};
|
|
46559
46608
|
|
|
@@ -48917,73 +48966,6 @@ function deriveTranscriptStatus(entries, opts = {}) {
|
|
|
48917
48966
|
return "running";
|
|
48918
48967
|
}
|
|
48919
48968
|
|
|
48920
|
-
// src/commands/sessions/shared/renderPrompt.ts
|
|
48921
|
-
function renderPrompt(raw) {
|
|
48922
|
-
const command = marker(raw, "command-name");
|
|
48923
|
-
if (command) {
|
|
48924
|
-
const args = marker(raw, "command-args");
|
|
48925
|
-
const name = `/${command.replace(/^\/+/, "")}`;
|
|
48926
|
-
return args ? `${name} ${args}` : name;
|
|
48927
|
-
}
|
|
48928
|
-
const bashInput = marker(raw, "bash-input");
|
|
48929
|
-
if (bashInput) return `! ${bashInput}`;
|
|
48930
|
-
return stripBlocks(raw);
|
|
48931
|
-
}
|
|
48932
|
-
function marker(raw, tag) {
|
|
48933
|
-
const match = raw.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
|
|
48934
|
-
return match ? match[1].trim() : "";
|
|
48935
|
-
}
|
|
48936
|
-
function stripBlocks(raw) {
|
|
48937
|
-
return raw.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "").replace(/<task-notification>[\s\S]*?<\/task-notification>/g, "").replace(/<command-[^>]*>[\s\S]*?<\/command-[^>]*>/g, "").replace(/<local-command-[^>]*>[\s\S]*?<\/local-command-[^>]*>/g, "").replace(/<bash-(stdout|stderr)>[\s\S]*?<\/bash-\1>/g, "").trim();
|
|
48938
|
-
}
|
|
48939
|
-
|
|
48940
|
-
// src/commands/sessions/shared/renderUserPrompt.ts
|
|
48941
|
-
var MAX_LENGTH = 2048;
|
|
48942
|
-
var INTERRUPT_PREFIX2 = "[Request interrupted";
|
|
48943
|
-
function renderUserPrompt(entry, maxLength = MAX_LENGTH) {
|
|
48944
|
-
if (entry.isSidechain || entry.isMeta) return void 0;
|
|
48945
|
-
if (entry.type !== "user" || isTaskNotification(entry)) return void 0;
|
|
48946
|
-
const raw = promptTextOrNull(entry);
|
|
48947
|
-
if (raw === null) return void 0;
|
|
48948
|
-
const message3 = renderPrompt(raw);
|
|
48949
|
-
return message3 ? cap(message3, maxLength) : void 0;
|
|
48950
|
-
}
|
|
48951
|
-
function isTaskNotification(entry) {
|
|
48952
|
-
return asRecord4(entry.origin)?.kind === "task-notification";
|
|
48953
|
-
}
|
|
48954
|
-
function promptTextOrNull(entry) {
|
|
48955
|
-
const content = asRecord4(entry.message)?.content;
|
|
48956
|
-
if (typeof content === "string") return isInterrupt(content) ? null : content;
|
|
48957
|
-
if (!Array.isArray(content)) return null;
|
|
48958
|
-
const parts = [];
|
|
48959
|
-
for (const block of content) {
|
|
48960
|
-
const b = asRecord4(block);
|
|
48961
|
-
if (b?.type !== "text") continue;
|
|
48962
|
-
const text18 = typeof b.text === "string" ? b.text : "";
|
|
48963
|
-
if (isInterrupt(text18)) return null;
|
|
48964
|
-
parts.push(text18);
|
|
48965
|
-
}
|
|
48966
|
-
return parts.length === 0 ? null : parts.join("\n");
|
|
48967
|
-
}
|
|
48968
|
-
function cap(message3, maxLength) {
|
|
48969
|
-
return message3.length <= maxLength ? message3 : `${message3.slice(0, maxLength).trimEnd()}\u2026`;
|
|
48970
|
-
}
|
|
48971
|
-
function isInterrupt(value) {
|
|
48972
|
-
return value.trimStart().startsWith(INTERRUPT_PREFIX2);
|
|
48973
|
-
}
|
|
48974
|
-
function asRecord4(value) {
|
|
48975
|
-
return value && typeof value === "object" ? value : null;
|
|
48976
|
-
}
|
|
48977
|
-
|
|
48978
|
-
// src/commands/sessions/shared/extractLastUserMessage.ts
|
|
48979
|
-
function extractLastUserMessage(entries, maxLength) {
|
|
48980
|
-
for (let i = entries.length - 1; i >= 0; i--) {
|
|
48981
|
-
const message3 = renderUserPrompt(entries[i], maxLength);
|
|
48982
|
-
if (message3) return message3;
|
|
48983
|
-
}
|
|
48984
|
-
return void 0;
|
|
48985
|
-
}
|
|
48986
|
-
|
|
48987
48969
|
// src/commands/sessions/shared/readTranscriptTail.ts
|
|
48988
48970
|
import * as fs52 from "fs";
|
|
48989
48971
|
var DEFAULT_MAX_BYTES = 256 * 1024;
|
|
@@ -49058,16 +49040,128 @@ function transcriptTailFingerprint(entries) {
|
|
|
49058
49040
|
return null;
|
|
49059
49041
|
}
|
|
49060
49042
|
|
|
49061
|
-
// src/commands/sessions/
|
|
49062
|
-
|
|
49063
|
-
|
|
49064
|
-
|
|
49065
|
-
|
|
49043
|
+
// src/commands/sessions/shared/extractLastAssistantMessage.ts
|
|
49044
|
+
var MAX_LENGTH = 500;
|
|
49045
|
+
function extractLastAssistantMessage(entries) {
|
|
49046
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
49047
|
+
const entry = entries[i];
|
|
49048
|
+
if (entry.isSidechain || entry.type !== "assistant") continue;
|
|
49049
|
+
const text18 = assistantText(entry);
|
|
49050
|
+
if (text18) return cap(text18);
|
|
49051
|
+
}
|
|
49052
|
+
return void 0;
|
|
49053
|
+
}
|
|
49054
|
+
function assistantText(entry) {
|
|
49055
|
+
const content = asRecord4(entry.message)?.content;
|
|
49056
|
+
if (!Array.isArray(content)) return "";
|
|
49057
|
+
const parts = [];
|
|
49058
|
+
for (const block of content) {
|
|
49059
|
+
const b = asRecord4(block);
|
|
49060
|
+
if (b?.type === "text" && typeof b.text === "string" && b.text.trim())
|
|
49061
|
+
parts.push(b.text.trim());
|
|
49062
|
+
}
|
|
49063
|
+
return parts.join("\n");
|
|
49064
|
+
}
|
|
49065
|
+
function cap(text18) {
|
|
49066
|
+
return text18.length <= MAX_LENGTH ? text18 : `${text18.slice(0, MAX_LENGTH).trimEnd()}\u2026`;
|
|
49067
|
+
}
|
|
49068
|
+
function asRecord4(value) {
|
|
49069
|
+
return value && typeof value === "object" ? value : null;
|
|
49070
|
+
}
|
|
49071
|
+
|
|
49072
|
+
// src/commands/sessions/shared/renderPrompt.ts
|
|
49073
|
+
function renderPrompt(raw) {
|
|
49074
|
+
const command = marker(raw, "command-name");
|
|
49075
|
+
if (command) {
|
|
49076
|
+
const args = marker(raw, "command-args");
|
|
49077
|
+
const name = `/${command.replace(/^\/+/, "")}`;
|
|
49078
|
+
return args ? `${name} ${args}` : name;
|
|
49079
|
+
}
|
|
49080
|
+
const bashInput = marker(raw, "bash-input");
|
|
49081
|
+
if (bashInput) return `! ${bashInput}`;
|
|
49082
|
+
return stripBlocks(raw);
|
|
49083
|
+
}
|
|
49084
|
+
function marker(raw, tag) {
|
|
49085
|
+
const match = raw.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
|
|
49086
|
+
return match ? match[1].trim() : "";
|
|
49087
|
+
}
|
|
49088
|
+
function stripBlocks(raw) {
|
|
49089
|
+
return raw.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "").replace(/<task-notification>[\s\S]*?<\/task-notification>/g, "").replace(/<command-[^>]*>[\s\S]*?<\/command-[^>]*>/g, "").replace(/<local-command-[^>]*>[\s\S]*?<\/local-command-[^>]*>/g, "").replace(/<bash-(stdout|stderr)>[\s\S]*?<\/bash-\1>/g, "").trim();
|
|
49090
|
+
}
|
|
49091
|
+
|
|
49092
|
+
// src/commands/sessions/shared/renderUserPrompt.ts
|
|
49093
|
+
var MAX_LENGTH2 = 2048;
|
|
49094
|
+
var INTERRUPT_PREFIX2 = "[Request interrupted";
|
|
49095
|
+
function renderUserPrompt(entry, maxLength = MAX_LENGTH2) {
|
|
49096
|
+
if (entry.isSidechain || entry.isMeta) return void 0;
|
|
49097
|
+
if (entry.type !== "user" || isTaskNotification(entry)) return void 0;
|
|
49098
|
+
const raw = promptTextOrNull(entry);
|
|
49099
|
+
if (raw === null) return void 0;
|
|
49100
|
+
const message3 = renderPrompt(raw);
|
|
49101
|
+
return message3 ? cap2(message3, maxLength) : void 0;
|
|
49102
|
+
}
|
|
49103
|
+
function isTaskNotification(entry) {
|
|
49104
|
+
return asRecord5(entry.origin)?.kind === "task-notification";
|
|
49105
|
+
}
|
|
49106
|
+
function promptTextOrNull(entry) {
|
|
49107
|
+
const content = asRecord5(entry.message)?.content;
|
|
49108
|
+
if (typeof content === "string") return isInterrupt(content) ? null : content;
|
|
49109
|
+
if (!Array.isArray(content)) return null;
|
|
49110
|
+
const parts = [];
|
|
49111
|
+
for (const block of content) {
|
|
49112
|
+
const b = asRecord5(block);
|
|
49113
|
+
if (b?.type !== "text") continue;
|
|
49114
|
+
const text18 = typeof b.text === "string" ? b.text : "";
|
|
49115
|
+
if (isInterrupt(text18)) return null;
|
|
49116
|
+
parts.push(text18);
|
|
49117
|
+
}
|
|
49118
|
+
return parts.length === 0 ? null : parts.join("\n");
|
|
49119
|
+
}
|
|
49120
|
+
function cap2(message3, maxLength) {
|
|
49121
|
+
return message3.length <= maxLength ? message3 : `${message3.slice(0, maxLength).trimEnd()}\u2026`;
|
|
49122
|
+
}
|
|
49123
|
+
function isInterrupt(value) {
|
|
49124
|
+
return value.trimStart().startsWith(INTERRUPT_PREFIX2);
|
|
49125
|
+
}
|
|
49126
|
+
function asRecord5(value) {
|
|
49127
|
+
return value && typeof value === "object" ? value : null;
|
|
49128
|
+
}
|
|
49129
|
+
|
|
49130
|
+
// src/commands/sessions/shared/extractLastUserMessage.ts
|
|
49131
|
+
function extractLastUserMessage(entries, maxLength) {
|
|
49132
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
49133
|
+
const message3 = renderUserPrompt(entries[i], maxLength);
|
|
49134
|
+
if (message3) return message3;
|
|
49135
|
+
}
|
|
49136
|
+
return void 0;
|
|
49137
|
+
}
|
|
49138
|
+
|
|
49139
|
+
// src/commands/sessions/daemon/updateLastMessages.ts
|
|
49140
|
+
function update3(session, field, message3, label) {
|
|
49141
|
+
if (message3 === session[field]) return false;
|
|
49142
|
+
session[field] = message3;
|
|
49066
49143
|
daemonLog(
|
|
49067
|
-
`session ${session.id} last
|
|
49144
|
+
`session ${session.id} last ${label} message: ${JSON.stringify(message3?.slice(0, 120) ?? null)}`
|
|
49145
|
+
);
|
|
49146
|
+
return true;
|
|
49147
|
+
}
|
|
49148
|
+
function updateLastMessages(session, entries, notify2) {
|
|
49149
|
+
const user = update3(
|
|
49150
|
+
session,
|
|
49151
|
+
"lastUserMessage",
|
|
49152
|
+
extractLastUserMessage(entries),
|
|
49153
|
+
"user"
|
|
49154
|
+
);
|
|
49155
|
+
const assistant = update3(
|
|
49156
|
+
session,
|
|
49157
|
+
"lastAssistantMessage",
|
|
49158
|
+
extractLastAssistantMessage(entries),
|
|
49159
|
+
"assistant"
|
|
49068
49160
|
);
|
|
49069
|
-
notify2?.();
|
|
49161
|
+
if (user || assistant) notify2?.();
|
|
49070
49162
|
}
|
|
49163
|
+
|
|
49164
|
+
// src/commands/sessions/daemon/reconcileTranscriptStatus.ts
|
|
49071
49165
|
function isFinished(session) {
|
|
49072
49166
|
return session.status === "done" || session.status === "error" || session.status === "stopped";
|
|
49073
49167
|
}
|
|
@@ -49079,7 +49173,7 @@ async function reconcileTranscriptStatus(session, onStatusChange, notify2) {
|
|
|
49079
49173
|
if (fingerprint !== null && fingerprint === session.transcriptFingerprint)
|
|
49080
49174
|
return;
|
|
49081
49175
|
session.transcriptFingerprint = fingerprint ?? void 0;
|
|
49082
|
-
|
|
49176
|
+
updateLastMessages(session, entries, notify2);
|
|
49083
49177
|
if (isFinished(session)) return;
|
|
49084
49178
|
const derived = deriveTranscriptStatus(entries, {
|
|
49085
49179
|
permissionActive: session.permissionActive
|
|
@@ -49312,7 +49406,7 @@ var sessionLimits = {
|
|
|
49312
49406
|
`refusing to spawn: at ceiling of ${ceiling} live sessions (sessions.maxLive)`
|
|
49313
49407
|
);
|
|
49314
49408
|
throw new Error(
|
|
49315
|
-
`session ceiling of ${ceiling} reached \u2014 raise it with: assist config set sessions.maxLive <n>
|
|
49409
|
+
`session ceiling of ${ceiling} reached \u2014 raise it with: assist config set sessions.maxLive <n> --node`
|
|
49316
49410
|
);
|
|
49317
49411
|
}
|
|
49318
49412
|
return String(counter.next++);
|
|
@@ -50063,7 +50157,7 @@ function restoreBase(id, persisted) {
|
|
|
50063
50157
|
}
|
|
50064
50158
|
|
|
50065
50159
|
// src/commands/sessions/daemon/deferredSession.ts
|
|
50066
|
-
function deferredSession(id, persisted,
|
|
50160
|
+
function deferredSession(id, persisted, cap3) {
|
|
50067
50161
|
return {
|
|
50068
50162
|
...restoreBase(id, persisted),
|
|
50069
50163
|
status: "stopped",
|
|
@@ -50077,13 +50171,13 @@ function deferredSession(id, persisted, cap2) {
|
|
|
50077
50171
|
runArgs: persisted.runArgs,
|
|
50078
50172
|
activity: persisted.activity,
|
|
50079
50173
|
restored: false,
|
|
50080
|
-
scrollback: deferralNotice(persisted,
|
|
50174
|
+
scrollback: deferralNotice(persisted, cap3)
|
|
50081
50175
|
};
|
|
50082
50176
|
}
|
|
50083
|
-
function deferralNotice(persisted,
|
|
50177
|
+
function deferralNotice(persisted, cap3) {
|
|
50084
50178
|
return [
|
|
50085
50179
|
`\r
|
|
50086
|
-
\x1B[33mNot resumed: restore was already at its cap of ${
|
|
50180
|
+
\x1B[33mNot resumed: restore was already at its cap of ${cap3} session(s) (raise it with: assist config set sessions.maxLive <n> --node)\x1B[0m\r
|
|
50087
50181
|
`,
|
|
50088
50182
|
`This card is the handle for it. Its command, working directory (${persisted.cwd})\r
|
|
50089
50183
|
`,
|
|
@@ -50639,23 +50733,23 @@ function logRestoreError(persisted, error) {
|
|
|
50639
50733
|
// src/commands/sessions/daemon/restoreAll.ts
|
|
50640
50734
|
function restoreAll(spawner, sessions) {
|
|
50641
50735
|
const persisted = dropUnrestorableSessions(loadPersistedSessions());
|
|
50642
|
-
const
|
|
50736
|
+
const cap3 = sessionLimits.maxRestore();
|
|
50643
50737
|
const restoredIds = /* @__PURE__ */ new Map();
|
|
50644
|
-
const names = persisted.slice(0,
|
|
50738
|
+
const names = persisted.slice(0, cap3).map((entry) => {
|
|
50645
50739
|
const id = restoreOne(entry, spawner, sessions);
|
|
50646
50740
|
if (entry.id != null && id != null) restoredIds.set(entry.id, id);
|
|
50647
50741
|
return entry.name;
|
|
50648
50742
|
});
|
|
50649
|
-
for (const over of persisted.slice(
|
|
50650
|
-
deferOne(over, spawner.recoveryCard,
|
|
50743
|
+
for (const over of persisted.slice(cap3))
|
|
50744
|
+
deferOne(over, spawner.recoveryCard, cap3);
|
|
50651
50745
|
remapLaunchedFrom(sessions, restoredIds);
|
|
50652
50746
|
return names;
|
|
50653
50747
|
}
|
|
50654
|
-
function deferOne(persisted, spawnRecoveryCard,
|
|
50748
|
+
function deferOne(persisted, spawnRecoveryCard, cap3) {
|
|
50655
50749
|
try {
|
|
50656
|
-
const id = spawnRecoveryCard((sid) => deferredSession(sid, persisted,
|
|
50750
|
+
const id = spawnRecoveryCard((sid) => deferredSession(sid, persisted, cap3));
|
|
50657
50751
|
daemonLog(
|
|
50658
|
-
`restore capped at ${
|
|
50752
|
+
`restore capped at ${cap3} (sessions.maxLive): ${describePersistedSession(persisted)} deferred to stopped card ${id}`
|
|
50659
50753
|
);
|
|
50660
50754
|
} catch (error) {
|
|
50661
50755
|
logDroppedSession(persisted, error);
|