hop2 0.11.0 → 0.11.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/.github/workflows/ci.yml +25 -0
- package/.github/workflows/publish.yml +130 -0
- package/DESIGN-input-acks.md +349 -0
- package/MULTI-AGENT-CHECKLIST.md +5 -5
- package/README-MCP.md +84 -5
- package/README.md +55 -4
- package/demo/README.md +52 -0
- package/demo/capture/capture-env.mjs +108 -0
- package/demo/capture/capture.mjs +634 -0
- package/demo/capture/dispatch-task.mjs +44 -0
- package/demo/capture/mcp-client.mjs +61 -0
- package/demo/capture/native-css.mjs +49 -0
- package/demo/capture/setup-04.mjs +67 -0
- package/demo/capture/setup-sessions.mjs +40 -0
- package/demo/capture/spawn-aurora.mjs +53 -0
- package/demo/capture/tools/agent.sh +30 -0
- package/demo/capture/tools/build.sh +18 -0
- package/demo/capture/tools/metrics.sh +17 -0
- package/docs/hero-overview.svg +119 -0
- package/docs/hero.svg +118 -0
- package/docs/restore-reliability.md +139 -0
- package/docs/session-identity.md +76 -0
- package/docs/switcher-first-ux.md +103 -0
- package/hay/CHANGELOG.md +59 -1
- package/hay/apps/cli/package.json +3 -2
- package/hay/apps/cli/src/index.ts +705 -28
- package/hay/apps/server/src/pty.ts +36 -2
- package/hay/apps/server/src/rooms.ts +525 -34
- package/hay/apps/server/test/rooms.test.ts +411 -1
- package/hay/apps/web/index.html +2 -0
- package/hay/apps/web/package.json +14 -12
- package/hay/apps/web/scripts/run-e2e.mjs +42 -5
- package/hay/apps/web/src/App.tsx +2492 -281
- package/hay/apps/web/src/components/ContextMenu.tsx +109 -0
- package/hay/apps/web/src/components/MobileKeyboard.tsx +135 -14
- package/hay/apps/web/src/components/SecondaryPane.tsx +218 -0
- package/hay/apps/web/src/components/SessionSwitcher.tsx +2525 -0
- package/hay/apps/web/src/setupTests.ts +23 -0
- package/hay/apps/web/src/styles.css +2460 -180
- package/hay/apps/web/src/utils/fileDrop.ts +15 -0
- package/hay/apps/web/src/utils/keyboardProtocol.ts +22 -0
- package/hay/apps/web/src/utils/optimisticEcho.ts +83 -7
- package/hay/apps/web/src/utils/scrollFlywheel.ts +145 -0
- package/hay/apps/web/src/utils/switcherModel.ts +314 -0
- package/hay/apps/web/src/utils/terminalSearch.ts +54 -0
- package/hay/apps/web/src/vite-env.d.ts +3 -0
- package/hay/apps/web/test/SessionSwitcher.test.tsx +324 -0
- package/hay/apps/web/test/fileDrop.test.ts +22 -0
- package/hay/apps/web/test/optimisticEcho.test.ts +17 -0
- package/hay/apps/web/test/scrollFlywheel.test.ts +113 -0
- package/hay/apps/web/test/switcherModel.test.ts +377 -0
- package/hay/apps/web/test/terminalSearch.test.ts +37 -0
- package/hay/apps/web/vite.config.ts +20 -0
- package/hay/package-lock.json +1696 -1171
- package/hay/packages/shared/src/protocol.ts +25 -2
- package/hay-web/assets/index-BohAWpcL.css +1 -0
- package/hay-web/assets/index-DfGT3DuO.js +130 -0
- package/hay-web/assets/index-DfGT3DuO.js.map +1 -0
- package/hay-web/index.html +4 -2
- package/hop +4348 -302
- package/hopa +465 -0
- package/mcp/hop-mcp.js +2878 -122
- package/package.json +7 -4
- package/scripts/claude-session-hook.js +152 -0
- package/scripts/hay-host.js +227 -4
- package/scripts/hop-math.js +316 -0
- package/scripts/salvage-and-restart-host.js +217 -0
- package/skills/hop-manager/SKILL.md +62 -0
- package/skills/hop-session/SKILL.md +42 -0
- package/skills/hopa/SKILL.md +75 -0
- package/tests/agent-skill.unit.test.cjs +60 -0
- package/tests/composer-state.unit.test.cjs +102 -0
- package/tests/hop-mcp.integration.test.cjs +476 -94
- package/tests/hopa-parity.unit.test.cjs +188 -0
- package/tests/readable-echo.unit.test.cjs +94 -0
- package/tests/readable-flush.unit.test.cjs +93 -0
- package/tests/submit-verification.unit.test.cjs +331 -0
- package/tests/terminal-api.integration.test.cjs +301 -13
- package/hay-web/assets/index-BzJB9r_I.js +0 -64
- package/hay-web/assets/index-BzJB9r_I.js.map +0 -1
- package/hay-web/assets/index-DG8Ntznc.css +0 -32
- package/sessions.html +0 -726
|
@@ -8,6 +8,14 @@ export type PtyFactoryOptions = {
|
|
|
8
8
|
cwd: string;
|
|
9
9
|
env?: Record<string, string>;
|
|
10
10
|
shell?: string;
|
|
11
|
+
// Launch the session ON this command instead of typing it into a shell
|
|
12
|
+
// afterwards. Restore used to attach, wait a fixed delay, and type the
|
|
13
|
+
// relaunch — which silently lost the keystrokes whenever the shell wasn't
|
|
14
|
+
// at its prompt yet. Passing the command as argv removes the whole class:
|
|
15
|
+
// there is no prompt to race, nothing to half-type, and no command echo in
|
|
16
|
+
// the scrollback. The shell is re-exec'd afterwards so the session behaves
|
|
17
|
+
// exactly as before once the command exits.
|
|
18
|
+
command?: string;
|
|
11
19
|
};
|
|
12
20
|
|
|
13
21
|
export type PtyFactory = (options: PtyFactoryOptions) => IPty;
|
|
@@ -25,7 +33,7 @@ const resolveShell = (shellOverride?: string) => {
|
|
|
25
33
|
return "/bin/bash";
|
|
26
34
|
};
|
|
27
35
|
|
|
28
|
-
export const createPty: PtyFactory = ({ cols, rows, cwd, env: envOverrides, shell }) => {
|
|
36
|
+
export const createPty: PtyFactory = ({ cols, rows, cwd, env: envOverrides, shell, command }) => {
|
|
29
37
|
const mode = process.env.PTY_MODE ?? "native";
|
|
30
38
|
if (mode === "mock") {
|
|
31
39
|
return createMockPty();
|
|
@@ -37,6 +45,12 @@ export const createPty: PtyFactory = ({ cols, rows, cwd, env: envOverrides, shel
|
|
|
37
45
|
env[key] = value;
|
|
38
46
|
}
|
|
39
47
|
}
|
|
48
|
+
// Shared PTYs get resized whenever a differently-sized device attaches
|
|
49
|
+
// (autofit claims), and every resize makes zsh re-emit its end-of-line
|
|
50
|
+
// mark ("%" + a line of spaces + CR) into history at the OLD width —
|
|
51
|
+
// rendering as stray reverse-video % at line ends for every later viewer.
|
|
52
|
+
// Suppress the mark for hop-spawned shells; user env overrides still win.
|
|
53
|
+
env.PROMPT_EOL_MARK = "";
|
|
40
54
|
if (envOverrides && typeof envOverrides === "object") {
|
|
41
55
|
for (const [key, value] of Object.entries(envOverrides)) {
|
|
42
56
|
if (!key || typeof value !== "string") continue;
|
|
@@ -47,7 +61,27 @@ export const createPty: PtyFactory = ({ cols, rows, cwd, env: envOverrides, shel
|
|
|
47
61
|
if (!env.COLORTERM) {
|
|
48
62
|
env.COLORTERM = "truecolor";
|
|
49
63
|
}
|
|
50
|
-
|
|
64
|
+
// A hop session is an INTERACTIVE terminal, so it must never inherit a
|
|
65
|
+
// "this output isn't for a human" color suppressor from whatever
|
|
66
|
+
// launched the daemon. Claude Code sets NO_COLOR=1 for the shells it
|
|
67
|
+
// runs commands in — so a daemon (re)started from inside an agent
|
|
68
|
+
// session propagated NO_COLOR into every PTY it spawned afterwards, and
|
|
69
|
+
// every app in every session silently went monochrome: measured, claude
|
|
70
|
+
// emits ZERO colored SGR with NO_COLOR=1 and full 24-bit truecolor
|
|
71
|
+
// without it. That is the whole "claude has no color in hop but does in
|
|
72
|
+
// iTerm" report. Explicit per-session env overrides above still win.
|
|
73
|
+
if (!envOverrides || !("NO_COLOR" in envOverrides)) delete env.NO_COLOR;
|
|
74
|
+
if (env.FORCE_COLOR === "0" && (!envOverrides || !("FORCE_COLOR" in envOverrides))) {
|
|
75
|
+
delete env.FORCE_COLOR;
|
|
76
|
+
}
|
|
77
|
+
const shellPath = resolveShell(shell);
|
|
78
|
+
// `-lc` runs the command in a login shell (rc files, aliases, PATH all
|
|
79
|
+
// as the user has them), then `exec <shell> -l` replaces it with the
|
|
80
|
+
// normal interactive shell, so exiting the app leaves a usable session.
|
|
81
|
+
const args = command
|
|
82
|
+
? ["-lc", `${command}; exec ${shellPath} -l`]
|
|
83
|
+
: [];
|
|
84
|
+
return pty.spawn(shellPath, args, {
|
|
51
85
|
cols,
|
|
52
86
|
rows,
|
|
53
87
|
cwd,
|