paseo-smart-session 1.2.6 → 2.1.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 +45 -134
- package/assets/LICENSE.lucide +43 -0
- package/assets/icon.png +0 -0
- package/assets/icon.svg +1 -0
- package/client/agents.ts +178 -0
- package/client/button-visibility.ts +32 -0
- package/client/display.tsx +102 -0
- package/client/guard/index.tsx +50 -0
- package/client/guard/paused.tsx +77 -0
- package/client/guard/pill-icons.tsx +26 -0
- package/client/guard/pills.ts +122 -0
- package/client/guard/settings.tsx +114 -0
- package/client/guard/surfaces.ts +2 -0
- package/client/guard/timeline.tsx +94 -0
- package/client/navigation.tsx +14 -0
- package/client/pill.tsx +12 -124
- package/client/sidebar-visibility.ts +21 -0
- package/client/surface.tsx +88 -3
- package/docs/navigation-verification.md +11 -0
- package/docs/screenshots/display-settings-desktop.png +0 -0
- package/docs/screenshots/display-settings-mobile.png +0 -0
- package/docs/session-guard.md +88 -0
- package/index.client.tsx +15 -4
- package/index.server.ts +9 -5
- package/mcp.mjs +32 -3
- package/package.json +6 -5
- package/paseo-plugin.json +2 -1
- package/server/guard/client.ts +27 -0
- package/server/guard/engine.ts +554 -0
- package/server/guard/index.ts +395 -0
- package/server/guard/labels.ts +77 -0
- package/server/guard/processes.ts +147 -0
- package/server/guard/standalone.ts +61 -0
- package/server/guard/store.ts +113 -0
- package/server/guard/timeline.ts +24 -0
- package/server/guard/usage.ts +57 -0
- package/server/install.ts +7 -7
- package/server/recorder.ts +2 -0
- package/server/session-mcp.ts +26 -0
- package/server/store.ts +25 -1
- package/shared/display.ts +11 -0
- package/shared/guard/contracts.ts +65 -0
- package/shared/guard/policy.ts +128 -0
- package/shared/guard/presentation.ts +85 -0
- package/shared/guard/timeline.ts +34 -0
- package/shared/lifecycle.ts +18 -0
- package/shared/smart-session.ts +1 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const TimelineDataSchema = z.object({
|
|
4
|
+
pauseId: z.string(), event: z.enum(["paused", "resumed", "released", "attention", "recovery"]),
|
|
5
|
+
at: z.string(), provider: z.string(), native: z.boolean(), autoResume: z.boolean(),
|
|
6
|
+
resetAt: z.string().nullable(), usedPct: z.number().nullable(), note: z.string().nullable(),
|
|
7
|
+
manualResume: z.boolean().optional(), demo: z.boolean().optional(), dismissed: z.boolean().optional(),
|
|
8
|
+
});
|
|
9
|
+
export type TimelineData = z.infer<typeof TimelineDataSchema>;
|
|
10
|
+
export const NotificationSchema = z.object({
|
|
11
|
+
id: z.string(), data: TimelineDataSchema, delivery: z.enum(["pending", "sending", "sent"]),
|
|
12
|
+
});
|
|
13
|
+
export type Notification = z.infer<typeof NotificationSchema>;
|
|
14
|
+
|
|
15
|
+
export function timelinePresentation(data: TimelineData) {
|
|
16
|
+
const provider = data.provider === "claude" ? "Claude" : data.provider === "codex" ? "Codex" : data.provider;
|
|
17
|
+
if (data.event === "released" && data.dismissed) return { title: "Pause dismissed", icon: "ShieldOff", tone: "muted" as const,
|
|
18
|
+
detail: "No message was sent. Protection is off for this session." + (data.native ? " Existing workers were released; their current work may continue." : "") };
|
|
19
|
+
if (data.event === "resumed") return { title: "Session resumed", icon: "Play", tone: "success" as const,
|
|
20
|
+
detail: data.manualResume ? "Resumed by you. Protection is off for this session; restore it from the composer pill when ready."
|
|
21
|
+
: data.native ? "Session and native subagents resumed after the quota reset." : "A continuation was sent after the quota reset." };
|
|
22
|
+
if (data.event === "released") return { title: data.native ? "Session released" : "Automatic resume cancelled", icon: "ShieldOff", tone: "muted" as const,
|
|
23
|
+
detail: data.note ?? (data.native ? "Suspended workers were released." : "Continue this session manually when ready.") };
|
|
24
|
+
if (data.event === "attention") return { title: "Pause needs attention", icon: "TriangleAlert", tone: "danger" as const,
|
|
25
|
+
detail: data.note ?? "Check this session before continuing manually." };
|
|
26
|
+
if (data.event === "recovery") return { title: "Waiting after Paseo restart", icon: "Pause", tone: "warning" as const,
|
|
27
|
+
detail: `The original workers ended, but this pause is saved. ${data.autoResume ? "Session Guard will continue this conversation after the quota resets." : "Automatic resume is off; continue manually when ready."} Your workspace and conversation remain in place.` };
|
|
28
|
+
if (data.demo) return { title: "Session Guard demo paused", icon: "Pause", tone: "warning" as const,
|
|
29
|
+
detail: "This empty test session is suspended so you can try Resume now. No provider quota was changed, and no task was sent. It will wait for you to resume it." };
|
|
30
|
+
const reset = data.resetAt ? Date.parse(data.resetAt) : NaN;
|
|
31
|
+
const resetLabel = Number.isFinite(reset) ? `Expected reset ${new Date(reset).toLocaleString([], { dateStyle: "short", timeStyle: "short" })}.` : "The provider has not reported a reset time yet.";
|
|
32
|
+
return { title: "Paused for session limit", icon: "Pause", tone: "warning" as const,
|
|
33
|
+
detail: `${provider}${data.usedPct === null ? "" : ` · ${data.usedPct}% used`}. ${data.native ? "This session and its native subagents are paused." : "The active turn was interrupted."} ${resetLabel} ${data.autoResume ? "Automatic resume was scheduled after reset confirmation." : "Automatic resume was off; continue manually when ready."}` };
|
|
34
|
+
}
|
package/shared/lifecycle.ts
CHANGED
|
@@ -15,3 +15,21 @@ export type Teardown = () => void | Promise<void>;
|
|
|
15
15
|
* exits and the plugin wedges at "Stopping" for the life of the daemon.
|
|
16
16
|
*/
|
|
17
17
|
export const lifecycle: { teardowns: Teardown[] } = { teardowns: [] };
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Runs every teardown even when one fails, then reports the first failure.
|
|
21
|
+
*
|
|
22
|
+
* One feature's cleanup throwing must not leave another's timer running: the
|
|
23
|
+
* subprocess would never exit and Paseo's stop step would hang.
|
|
24
|
+
*/
|
|
25
|
+
export async function runTeardowns(teardowns: readonly Teardown[]): Promise<void> {
|
|
26
|
+
let failure: unknown = null;
|
|
27
|
+
for (const teardown of teardowns) {
|
|
28
|
+
try {
|
|
29
|
+
await teardown();
|
|
30
|
+
} catch (error) {
|
|
31
|
+
failure ??= error;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
if (failure !== null) throw failure;
|
|
35
|
+
}
|
package/shared/smart-session.ts
CHANGED
|
@@ -109,7 +109,7 @@ export const InstallReportSchema = z.object({
|
|
|
109
109
|
settingsPath: z.string(),
|
|
110
110
|
changed: z.boolean(),
|
|
111
111
|
hooks: z.array(z.string()),
|
|
112
|
-
mcp: z.enum(["present", "added", "updated", "unavailable", "skipped"]),
|
|
112
|
+
mcp: z.enum(["present", "added", "updated", "unavailable", "skipped", "session"]),
|
|
113
113
|
error: z.string().nullable(),
|
|
114
114
|
});
|
|
115
115
|
|