@staff0rd/assist 0.297.3 → 0.298.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/dist/commands/sessions/web/bundle.js +56 -56
- package/dist/index.js +83 -38
- 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.298.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -4897,17 +4897,25 @@ async function deleteItemComment(res, itemId, commentId) {
|
|
|
4897
4897
|
|
|
4898
4898
|
// src/commands/backlog/web/rewindItemPhase.ts
|
|
4899
4899
|
import { eq as eq14 } from "drizzle-orm";
|
|
4900
|
+
|
|
4901
|
+
// src/commands/backlog/resolveRewindPlan.ts
|
|
4902
|
+
function resolveRewindPlan(item) {
|
|
4903
|
+
return [...resolvePlan(item), buildReviewPhase()];
|
|
4904
|
+
}
|
|
4905
|
+
|
|
4906
|
+
// src/commands/backlog/web/rewindItemPhase.ts
|
|
4900
4907
|
async function rewindItemPhase(req, res, id2) {
|
|
4901
4908
|
const { phase, reason } = await parseRewindBody(req);
|
|
4902
4909
|
const result = await findItemOr404(res, id2);
|
|
4903
4910
|
if (!result) return;
|
|
4904
4911
|
const { orm, item } = result;
|
|
4905
|
-
const
|
|
4912
|
+
const plan2 = resolveRewindPlan(item);
|
|
4913
|
+
const error = validateRewind(item, plan2, phase);
|
|
4906
4914
|
if (error) {
|
|
4907
4915
|
respondJson(res, 400, { error });
|
|
4908
4916
|
return;
|
|
4909
4917
|
}
|
|
4910
|
-
const phaseName =
|
|
4918
|
+
const phaseName = plan2[phase - 1].name;
|
|
4911
4919
|
await appendComment(
|
|
4912
4920
|
orm,
|
|
4913
4921
|
id2,
|
|
@@ -4917,12 +4925,9 @@ async function rewindItemPhase(req, res, id2) {
|
|
|
4917
4925
|
await orm.update(items).set({ currentPhase: phase, status: "in-progress" }).where(eq14(items.id, id2));
|
|
4918
4926
|
respondJson(res, 200, await loadItem(orm, id2));
|
|
4919
4927
|
}
|
|
4920
|
-
function validateRewind(item, phase) {
|
|
4921
|
-
if (
|
|
4922
|
-
return
|
|
4923
|
-
}
|
|
4924
|
-
if (phase < 1 || phase > item.plan.length) {
|
|
4925
|
-
return `Phase ${phase} does not exist. Valid range: 1\u2013${item.plan.length}.`;
|
|
4928
|
+
function validateRewind(item, plan2, phase) {
|
|
4929
|
+
if (phase < 1 || phase > plan2.length) {
|
|
4930
|
+
return `Phase ${phase} does not exist. Valid range: 1\u2013${plan2.length}.`;
|
|
4926
4931
|
}
|
|
4927
4932
|
const currentPhase = item.currentPhase ?? 1;
|
|
4928
4933
|
if (phase >= currentPhase) {
|
|
@@ -6832,12 +6837,9 @@ function registerRefineCommand(cmd) {
|
|
|
6832
6837
|
|
|
6833
6838
|
// src/commands/backlog/rewindPhase.ts
|
|
6834
6839
|
import chalk66 from "chalk";
|
|
6835
|
-
function validateRewind2(item, phaseNumber) {
|
|
6836
|
-
if (
|
|
6837
|
-
return `
|
|
6838
|
-
}
|
|
6839
|
-
if (phaseNumber < 1 || phaseNumber > item.plan.length) {
|
|
6840
|
-
return `Phase ${phaseNumber} does not exist. Valid range: 1\u2013${item.plan.length}.`;
|
|
6840
|
+
function validateRewind2(item, plan2, phaseNumber) {
|
|
6841
|
+
if (phaseNumber < 1 || phaseNumber > plan2.length) {
|
|
6842
|
+
return `Phase ${phaseNumber} does not exist. Valid range: 1\u2013${plan2.length}.`;
|
|
6841
6843
|
}
|
|
6842
6844
|
const currentPhase = item.currentPhase ?? 1;
|
|
6843
6845
|
if (phaseNumber >= currentPhase) {
|
|
@@ -6854,13 +6856,14 @@ async function rewindPhase(id2, phase, opts) {
|
|
|
6854
6856
|
console.log(chalk66.red(`Item #${id2} not found.`));
|
|
6855
6857
|
return;
|
|
6856
6858
|
}
|
|
6857
|
-
const
|
|
6859
|
+
const plan2 = resolveRewindPlan(item);
|
|
6860
|
+
const error = validateRewind2(item, plan2, phaseNumber);
|
|
6858
6861
|
if (error) {
|
|
6859
6862
|
console.log(chalk66.red(error));
|
|
6860
6863
|
process.exitCode = 1;
|
|
6861
6864
|
return;
|
|
6862
6865
|
}
|
|
6863
|
-
const phaseName =
|
|
6866
|
+
const phaseName = plan2[phaseIndex].name;
|
|
6864
6867
|
await appendComment(
|
|
6865
6868
|
orm,
|
|
6866
6869
|
item.id,
|
|
@@ -18409,6 +18412,44 @@ function daemonLog(message) {
|
|
|
18409
18412
|
console.log(`${(/* @__PURE__ */ new Date()).toISOString()} [${process.pid}] ${message}`);
|
|
18410
18413
|
}
|
|
18411
18414
|
|
|
18415
|
+
// src/commands/sessions/daemon/loadActiveSelection.ts
|
|
18416
|
+
import { z as z5 } from "zod";
|
|
18417
|
+
var ACTIVE_FILE = "active.json";
|
|
18418
|
+
var activeSelectionSchema = z5.record(z5.string(), z5.string());
|
|
18419
|
+
function loadActiveSelection() {
|
|
18420
|
+
const parsed = activeSelectionSchema.safeParse(
|
|
18421
|
+
loadJson(ACTIVE_FILE)
|
|
18422
|
+
);
|
|
18423
|
+
return parsed.success ? parsed.data : {};
|
|
18424
|
+
}
|
|
18425
|
+
function saveActiveSelection(active) {
|
|
18426
|
+
saveJson(ACTIVE_FILE, active);
|
|
18427
|
+
}
|
|
18428
|
+
|
|
18429
|
+
// src/commands/sessions/daemon/ActiveSelection.ts
|
|
18430
|
+
var ActiveSelection = class {
|
|
18431
|
+
// why: onChange triggers a broadcast only when the selection actually changes
|
|
18432
|
+
constructor(onChange) {
|
|
18433
|
+
this.onChange = onChange;
|
|
18434
|
+
}
|
|
18435
|
+
byRepo = /* @__PURE__ */ new Map();
|
|
18436
|
+
set(cwd, sessionId) {
|
|
18437
|
+
if (!cwd) return;
|
|
18438
|
+
this.byRepo.delete(cwd);
|
|
18439
|
+
this.byRepo.set(cwd, sessionId);
|
|
18440
|
+
saveActiveSelection(this.toJSON());
|
|
18441
|
+
this.onChange();
|
|
18442
|
+
}
|
|
18443
|
+
// why: on daemon restart, reload persisted selections but drop any whose session was not restored
|
|
18444
|
+
restore(isLive) {
|
|
18445
|
+
for (const [cwd, sessionId] of Object.entries(loadActiveSelection()))
|
|
18446
|
+
if (isLive(sessionId)) this.byRepo.set(cwd, sessionId);
|
|
18447
|
+
}
|
|
18448
|
+
toJSON() {
|
|
18449
|
+
return Object.fromEntries(this.byRepo);
|
|
18450
|
+
}
|
|
18451
|
+
};
|
|
18452
|
+
|
|
18412
18453
|
// src/commands/sessions/daemon/broadcast.ts
|
|
18413
18454
|
function sendTo(client, msg) {
|
|
18414
18455
|
client.send(JSON.stringify(msg));
|
|
@@ -18421,17 +18462,17 @@ function broadcast(clients, msg) {
|
|
|
18421
18462
|
}
|
|
18422
18463
|
|
|
18423
18464
|
// src/commands/sessions/daemon/loadPersistedSessions.ts
|
|
18424
|
-
import { z as
|
|
18465
|
+
import { z as z6 } from "zod";
|
|
18425
18466
|
var SESSIONS_FILE = "sessions.json";
|
|
18426
|
-
var persistedSessionSchema =
|
|
18427
|
-
name:
|
|
18428
|
-
commandType:
|
|
18429
|
-
cwd:
|
|
18430
|
-
startedAt:
|
|
18431
|
-
claudeSessionId:
|
|
18432
|
-
runName:
|
|
18433
|
-
runArgs:
|
|
18434
|
-
assistArgs:
|
|
18467
|
+
var persistedSessionSchema = z6.object({
|
|
18468
|
+
name: z6.string(),
|
|
18469
|
+
commandType: z6.enum(["claude", "run", "assist"]),
|
|
18470
|
+
cwd: z6.string(),
|
|
18471
|
+
startedAt: z6.number(),
|
|
18472
|
+
claudeSessionId: z6.string().optional(),
|
|
18473
|
+
runName: z6.string().optional(),
|
|
18474
|
+
runArgs: z6.array(z6.string()).optional(),
|
|
18475
|
+
assistArgs: z6.array(z6.string()).optional(),
|
|
18435
18476
|
activity: activitySchema.optional()
|
|
18436
18477
|
});
|
|
18437
18478
|
function loadPersistedSessions() {
|
|
@@ -18498,11 +18539,13 @@ function toSessionInfo({
|
|
|
18498
18539
|
}
|
|
18499
18540
|
|
|
18500
18541
|
// src/commands/sessions/daemon/broadcastSessions.ts
|
|
18501
|
-
function broadcastSessions(sessions, clients, windowsSessions = []) {
|
|
18542
|
+
function broadcastSessions(sessions, clients, windowsSessions = [], active) {
|
|
18502
18543
|
persistLiveSessions(sessions);
|
|
18544
|
+
const local = [...sessions.values()].map(toSessionInfo);
|
|
18503
18545
|
broadcast(clients, {
|
|
18504
18546
|
type: "sessions",
|
|
18505
|
-
sessions:
|
|
18547
|
+
sessions: local.concat(windowsSessions),
|
|
18548
|
+
active: active?.toJSON() ?? {}
|
|
18506
18549
|
});
|
|
18507
18550
|
}
|
|
18508
18551
|
|
|
@@ -18640,8 +18683,7 @@ function replayScrollback(sessions, client) {
|
|
|
18640
18683
|
}
|
|
18641
18684
|
|
|
18642
18685
|
// src/commands/sessions/daemon/greetClient.ts
|
|
18643
|
-
function greetClient(client, sessions,
|
|
18644
|
-
sendTo(client, { type: "sessions", sessions: list4() });
|
|
18686
|
+
function greetClient(client, sessions, windowsProxy) {
|
|
18645
18687
|
replayScrollback(sessions, client);
|
|
18646
18688
|
windowsProxy.replayScrollback(client);
|
|
18647
18689
|
void windowsProxy.discover();
|
|
@@ -19685,6 +19727,8 @@ var SessionManager = class {
|
|
|
19685
19727
|
this.onIdleChange = onIdleChange;
|
|
19686
19728
|
}
|
|
19687
19729
|
sessions = /* @__PURE__ */ new Map();
|
|
19730
|
+
// why: dispatch calls active.set() on card click; broadcasts include active.toJSON()
|
|
19731
|
+
active = new ActiveSelection(() => this.notify());
|
|
19688
19732
|
clients = new ClientHub();
|
|
19689
19733
|
nextId = 1;
|
|
19690
19734
|
shuttingDown = false;
|
|
@@ -19692,16 +19736,14 @@ var SessionManager = class {
|
|
|
19692
19736
|
windowsProxy = new WindowsProxy(this.clients, () => this.notify());
|
|
19693
19737
|
addClient(client) {
|
|
19694
19738
|
this.clients.add(client);
|
|
19695
|
-
this.
|
|
19696
|
-
greetClient(client, this.sessions, this.
|
|
19739
|
+
this.notify();
|
|
19740
|
+
greetClient(client, this.sessions, this.windowsProxy);
|
|
19697
19741
|
}
|
|
19698
19742
|
removeClient(client) {
|
|
19699
19743
|
this.clients.delete(client);
|
|
19700
19744
|
this.onIdleChange?.(this.isIdle());
|
|
19701
19745
|
}
|
|
19702
|
-
isIdle()
|
|
19703
|
-
return this.sessions.size === 0 && this.clients.size === 0;
|
|
19704
|
-
}
|
|
19746
|
+
isIdle = () => this.sessions.size === 0 && this.clients.size === 0;
|
|
19705
19747
|
shutdown() {
|
|
19706
19748
|
this.shuttingDown = true;
|
|
19707
19749
|
shutdownSessions(this.sessions);
|
|
@@ -19769,7 +19811,7 @@ var SessionManager = class {
|
|
|
19769
19811
|
notify = () => {
|
|
19770
19812
|
if (this.shuttingDown) return;
|
|
19771
19813
|
const windows = this.windowsProxy.sessions();
|
|
19772
|
-
broadcastSessions(this.sessions, this.clients, windows);
|
|
19814
|
+
broadcastSessions(this.sessions, this.clients, windows, this.active);
|
|
19773
19815
|
this.onIdleChange?.(this.isIdle());
|
|
19774
19816
|
};
|
|
19775
19817
|
};
|
|
@@ -19947,7 +19989,8 @@ var handlers = {
|
|
|
19947
19989
|
),
|
|
19948
19990
|
"set-autoadvance": routed(
|
|
19949
19991
|
(_client, m, d) => m.setAutoAdvance(d.sessionId, d.enabled)
|
|
19950
|
-
)
|
|
19992
|
+
),
|
|
19993
|
+
"set-active": (_client, m, d) => m.active.set(d.cwd, d.sessionId)
|
|
19951
19994
|
};
|
|
19952
19995
|
function dispatchMessage(client, manager, data) {
|
|
19953
19996
|
handlers[data.type]?.(client, manager, data);
|
|
@@ -20018,6 +20061,8 @@ function onListening(manager, checkAutoExit) {
|
|
|
20018
20061
|
});
|
|
20019
20062
|
process.on("exit", cleanupOwnedFiles);
|
|
20020
20063
|
const restored = manager.restore();
|
|
20064
|
+
const liveIds = new Set(manager.listSessions().map((s) => s.id));
|
|
20065
|
+
manager.active.restore((id2) => liveIds.has(id2));
|
|
20021
20066
|
daemonLog(
|
|
20022
20067
|
restored.length > 0 ? `restored ${restored.length} session(s): ${restored.join(", ")}` : "no persisted sessions to restore"
|
|
20023
20068
|
);
|