@hwip/cli 0.1.6 → 0.1.8

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/listener.js CHANGED
@@ -36,6 +36,7 @@ const os_1 = require("os");
36
36
  const path_1 = require("path");
37
37
  const ws_1 = __importDefault(require("ws"));
38
38
  const config_js_1 = require("./config.js");
39
+ const agent_dirs_js_1 = require("./agent-dirs.js");
39
40
  const api_js_1 = require("./api.js");
40
41
  const shell_audit_js_1 = require("./shell-audit.js");
41
42
  const insecure_url_js_1 = require("./insecure-url.js");
@@ -1493,7 +1494,10 @@ const handleSessionResumeRequest = (req, send) => {
1493
1494
  ? [';', 'set-option', config_js_1.SESSION_PROJECT_OPTION, known.project, ';', 'set-option', config_js_1.SESSION_LABEL_OPTION, known.label]
1494
1495
  : [];
1495
1496
  const conversation = resumableConversation(agent, known);
1496
- const started = (0, child_process_1.spawnSync)('tmux', (0, tmux_socket_js_1.tmuxArgs)(['new-session', '-d', '-s', target, '-c', known.cwd, agent.binary, ...(conversation?.args ?? []), ...sidecar]), { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'] });
1497
+ // tmux gives the new pane this client's PATH. A login service's PATH has none
1498
+ // of the agent directories, so they go on as schedule launches add them —
1499
+ // otherwise the agent is not found and the session ends as it starts.
1500
+ const started = (0, child_process_1.spawnSync)('tmux', (0, tmux_socket_js_1.tmuxArgs)(['new-session', '-d', '-s', target, '-c', known.cwd, agent.binary, ...(conversation?.args ?? []), ...sidecar]), { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'], env: { ...process.env, PATH: (0, agent_dirs_js_1.withAgentDirs)(process.env.PATH) } });
1497
1501
  if (started.status !== 0) {
1498
1502
  (0, listener_log_js_1.log)(`✗ resume ${sessionName}: tmux refused (${(started.stderr ?? '').trim() || 'no detail'})`);
1499
1503
  return reply({ error: 'start_failed' });
package/dist/templates.js CHANGED
@@ -789,6 +789,17 @@ const LOOKUP_TIMEOUT_MS = 5000;
789
789
  const RESUBSCRIBE_MIN_MS = 1000;
790
790
  const RESUBSCRIBE_MAX_MS = 30000;
791
791
 
792
+ // The newest instance per directory. 2.x evicts a directory's instance after an
793
+ // idle hour (\`experimental.location_idle_timeout\`) and runs \`setup\` again on the
794
+ // next request, but hands \`setup\` no way to learn of the eviction — and the
795
+ // evicted instance's stream keeps delivering. Each eviction would leave one more
796
+ // loop pushing every turn. The module is evaluated afresh per instance (2.1.2,
797
+ // 2026-10-22), so only \`globalThis\` outlives one; an outdated loop stops at its
798
+ // next event.
799
+ const CURRENT_KEY = Symbol.for("hwip.opencode.current");
800
+ const currentByDirectory = (): Map<string, object> =>
801
+ ((globalThis as Record<symbol, Map<string, object> | undefined>)[CURRENT_KEY] ??= new Map());
802
+
792
803
  const setup = (ctx: V2Context): void => {
793
804
  // 1.18 calls \`setup\` as well as \`server\`, with a context that has no event
794
805
  // stream. Its hooks are \`server\`'s, so there is nothing to do here.
@@ -797,6 +808,10 @@ const setup = (ctx: V2Context): void => {
797
808
  const subscribe = stream.subscribe.bind(stream);
798
809
  const here = ctx.location?.directory;
799
810
  const turns = createTurns();
811
+ const instance = {};
812
+ const key = here ?? "";
813
+ currentByDirectory().set(key, instance);
814
+ const outdated = (): boolean => currentByDirectory().get(key) !== instance;
800
815
 
801
816
  // One server runs an instance of this plugin per directory and hands every
802
817
  // instance every session's events, so the session's own directory decides
@@ -854,9 +869,10 @@ const setup = (ctx: V2Context): void => {
854
869
  // \`notify\` drops them — there is no channel the user would read.
855
870
  const consume = async (): Promise<void> => {
856
871
  let wait = RESUBSCRIBE_MIN_MS;
857
- for (;;) {
872
+ while (!outdated()) {
858
873
  try {
859
874
  for await (const event of subscribe()) {
875
+ if (outdated()) return;
860
876
  wait = RESUBSCRIBE_MIN_MS;
861
877
  try {
862
878
  await handle(event);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hwip/cli",
3
- "version": "0.1.6",
3
+ "version": "0.1.8",
4
4
  "description": "Hwip CLI + push notification SDK for AI agents",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",