@wrongstack/runtime 0.319.0 → 1.0.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/clipboard.js CHANGED
@@ -4,6 +4,7 @@ import { randomUUID } from "node:crypto";
4
4
  import * as fs from "node:fs/promises";
5
5
  import * as os from "node:os";
6
6
  import * as path from "node:path";
7
+ import { StringDecoder } from "node:string_decoder";
7
8
  import { buildChildEnv } from "@wrongstack/core/utils";
8
9
  var MAX_IMAGE_BYTES = 10 * 1024 * 1024;
9
10
  var MAX_TEXT_BYTES = 4 * 1024 * 1024;
@@ -145,6 +146,7 @@ function runCmd(cmd, args) {
145
146
  stdio: ["ignore", "pipe", "pipe"],
146
147
  windowsHide: true
147
148
  });
149
+ const decoder = new StringDecoder("utf8");
148
150
  let out = "";
149
151
  let outBytes = 0;
150
152
  let settled = false;
@@ -171,12 +173,13 @@ function runCmd(cmd, args) {
171
173
  finish(null);
172
174
  return;
173
175
  }
174
- out += chunk.toString("utf8");
176
+ out += decoder.write(chunk);
175
177
  };
176
178
  child.stdout.on("data", onStdoutData);
177
179
  child.on("error", () => finish(null));
178
180
  child.on("exit", (code) => {
179
181
  if (killedByTimeout) return finish(null);
182
+ out += decoder.end();
180
183
  finish(code === 0 ? out : null);
181
184
  });
182
185
  });
package/dist/host.js CHANGED
@@ -20,65 +20,59 @@ async function applyWrongStackPack(host, pack, opts = {}) {
20
20
  const registeredToolNames = [];
21
21
  const registeredCommandNames = [];
22
22
  const registeredProviderTypes = [];
23
- if (pack.tools) {
24
- const tools = [...pack.tools];
25
- host.tools.registerAllOrThrow(tools, owner);
26
- for (const t of tools) registeredToolNames.push(t.name);
27
- }
28
- if (pack.providers) {
29
- const providers = [...pack.providers];
30
- host.providers.registerAll(providers);
31
- for (const p of providers) registeredProviderTypes.push(p.type);
32
- }
33
- if (pack.slashCommands) {
34
- const cmds = [...pack.slashCommands];
35
- host.slashCommands.registerAll(cmds, owner);
36
- for (const c of cmds)
37
- registeredCommandNames.push(owner === "core" ? c.name : `${owner}:${c.name}`);
38
- }
39
- if (pack.extensions && host.extensions) {
40
- for (const ext of pack.extensions) {
41
- unregisterExtensions.push(host.extensions.register(ext));
23
+ const rollback = () => {
24
+ for (let i = unregisterExtensions.length - 1; i >= 0; i--) {
25
+ unregisterExtensions[i]();
42
26
  }
43
- }
44
- if (pack.setup) {
45
- if (!opts.api) {
46
- throw new Error(`Pack "${pack.name}" defines setup() but no PluginAPI was provided`);
27
+ for (let i = registeredCommandNames.length - 1; i >= 0; i--) {
28
+ host.slashCommands.unregister(registeredCommandNames[i]);
47
29
  }
48
- try {
49
- await pack.setup(opts.api);
50
- } catch (setupErr) {
51
- for (let i = unregisterExtensions.length - 1; i >= 0; i--) {
52
- unregisterExtensions[i]();
30
+ for (let i = registeredToolNames.length - 1; i >= 0; i--) {
31
+ host.tools.unregister(registeredToolNames[i]);
32
+ }
33
+ for (let i = registeredProviderTypes.length - 1; i >= 0; i--) {
34
+ host.providers.unregister(registeredProviderTypes[i]);
35
+ }
36
+ };
37
+ try {
38
+ if (pack.tools) {
39
+ for (const t of pack.tools) {
40
+ host.tools.register(t, owner);
41
+ registeredToolNames.push(t.name);
53
42
  }
54
- for (let i = registeredCommandNames.length - 1; i >= 0; i--) {
55
- host.slashCommands.unregister(registeredCommandNames[i]);
43
+ }
44
+ if (pack.providers) {
45
+ for (const p of pack.providers) {
46
+ host.providers.register(p);
47
+ registeredProviderTypes.push(p.type);
56
48
  }
57
- for (let i = registeredToolNames.length - 1; i >= 0; i--) {
58
- host.tools.unregister(registeredToolNames[i]);
49
+ }
50
+ if (pack.slashCommands) {
51
+ for (const c of pack.slashCommands) {
52
+ host.slashCommands.register(c, owner);
53
+ registeredCommandNames.push(owner === "core" ? c.name : `${owner}:${c.name}`);
59
54
  }
60
- for (let i = registeredProviderTypes.length - 1; i >= 0; i--) {
61
- host.providers.unregister(registeredProviderTypes[i]);
55
+ }
56
+ if (pack.extensions && host.extensions) {
57
+ for (const ext of pack.extensions) {
58
+ unregisterExtensions.push(host.extensions.register(ext));
62
59
  }
63
- throw setupErr;
64
60
  }
61
+ if (pack.setup) {
62
+ if (!opts.api) {
63
+ throw new Error(`Pack "${pack.name}" defines setup() but no PluginAPI was provided`);
64
+ }
65
+ await pack.setup(opts.api);
66
+ }
67
+ } catch (mountErr) {
68
+ rollback();
69
+ throw mountErr;
65
70
  }
66
71
  return {
67
72
  pack,
68
73
  owner,
69
74
  async teardown() {
70
- for (let i = unregisterExtensions.length - 1; i >= 0; i--) {
71
- unregisterExtensions[i]();
72
- }
73
- for (let i = registeredCommandNames.length - 1; i >= 0; i--) {
74
- host.slashCommands.unregister(registeredCommandNames[i]);
75
- }
76
- for (let i = registeredToolNames.length - 1; i >= 0; i--) {
77
- host.tools.unregister(registeredToolNames[i]);
78
- }
79
- for (let i = registeredProviderTypes.length - 1; i >= 0; i--) {
80
- host.providers.unregister(registeredProviderTypes[i]);
81
- }
75
+ rollback();
82
76
  if (pack.teardown) {
83
77
  if (!opts.api) {
84
78
  throw new Error(`Pack "${pack.name}" defines teardown() but no PluginAPI was provided`);
package/dist/index.js CHANGED
@@ -4,6 +4,7 @@ import { randomUUID } from "node:crypto";
4
4
  import * as fs from "node:fs/promises";
5
5
  import * as os from "node:os";
6
6
  import * as path from "node:path";
7
+ import { StringDecoder } from "node:string_decoder";
7
8
  import { buildChildEnv } from "@wrongstack/core/utils";
8
9
  var MAX_IMAGE_BYTES = 10 * 1024 * 1024;
9
10
  var MAX_TEXT_BYTES = 4 * 1024 * 1024;
@@ -145,6 +146,7 @@ function runCmd(cmd, args) {
145
146
  stdio: ["ignore", "pipe", "pipe"],
146
147
  windowsHide: true
147
148
  });
149
+ const decoder = new StringDecoder("utf8");
148
150
  let out = "";
149
151
  let outBytes = 0;
150
152
  let settled = false;
@@ -171,12 +173,13 @@ function runCmd(cmd, args) {
171
173
  finish(null);
172
174
  return;
173
175
  }
174
- out += chunk.toString("utf8");
176
+ out += decoder.write(chunk);
175
177
  };
176
178
  child.stdout.on("data", onStdoutData);
177
179
  child.on("error", () => finish(null));
178
180
  child.on("exit", (code) => {
179
181
  if (killedByTimeout) return finish(null);
182
+ out += decoder.end();
180
183
  finish(code === 0 ? out : null);
181
184
  });
182
185
  });
@@ -289,7 +292,8 @@ import {
289
292
  import {
290
293
  DefaultConfigStore,
291
294
  DefaultSessionStore,
292
- getSessionRegistry
295
+ getSessionRegistry,
296
+ resolveSessionLoggingConfig
293
297
  } from "@wrongstack/core/storage";
294
298
  import { createProjectSageMemoryPort, isSqliteAvailable } from "@wrongstack/sage";
295
299
  function createDefaultContainer(opts) {
@@ -325,15 +329,16 @@ function createDefaultContainer(opts) {
325
329
  );
326
330
  const modeStore = new DefaultModeStore({ directory: wpaths.configDir });
327
331
  container.bind(TOKENS.ModeStore, () => modeStore);
328
- container.bind(
329
- TOKENS.SessionStore,
330
- () => new DefaultSessionStore({
332
+ container.bind(TOKENS.SessionStore, () => {
333
+ const sessionLogging = resolveSessionLoggingConfig(config);
334
+ const store = new DefaultSessionStore({
331
335
  dir: wpaths.projectSessions,
332
336
  projectRoot: wpaths.projectRoot,
333
337
  logger,
334
338
  // Scrub secrets out of persisted user/model turns (F-06). Tool output
335
339
  // is already scrubbed by the executor.
336
340
  secretScrubber: container.resolve(TOKENS.SecretScrubber),
341
+ storage: sessionLogging.storage,
337
342
  // Cross-process guard consulted by delete(): refuses to remove a
338
343
  // session that a LIVE terminal/TUI/WebUI in this project is using.
339
344
  isSessionInUse: async (sessionId) => {
@@ -348,8 +353,21 @@ function createDefaultContainer(opts) {
348
353
  }
349
354
  return null;
350
355
  }
351
- })
352
- );
356
+ });
357
+ if (sessionLogging.storage.autoArchive) {
358
+ void store.archiveIdle({
359
+ hotKeepSessions: sessionLogging.storage.hotKeepSessions,
360
+ includeSubagents: sessionLogging.storage.includeSubagents,
361
+ backfill: true
362
+ })?.catch((error) => {
363
+ logger.warn("Session archive-idle failed", {
364
+ event: "session_store.archive_idle_failed",
365
+ message: error instanceof Error ? error.message : String(error)
366
+ });
367
+ });
368
+ }
369
+ return store;
370
+ });
353
371
  if (!isSqliteAvailable()) {
354
372
  throw new Error(
355
373
  "SAGE requires synchronous SQLite (node:sqlite on Node >= 22.5 or bun:sqlite on Bun). The JSONL compatibility fallback has been removed."
@@ -727,65 +745,59 @@ async function applyWrongStackPack(host, pack, opts = {}) {
727
745
  const registeredToolNames = [];
728
746
  const registeredCommandNames = [];
729
747
  const registeredProviderTypes = [];
730
- if (pack.tools) {
731
- const tools = [...pack.tools];
732
- host.tools.registerAllOrThrow(tools, owner);
733
- for (const t of tools) registeredToolNames.push(t.name);
734
- }
735
- if (pack.providers) {
736
- const providers = [...pack.providers];
737
- host.providers.registerAll(providers);
738
- for (const p of providers) registeredProviderTypes.push(p.type);
739
- }
740
- if (pack.slashCommands) {
741
- const cmds = [...pack.slashCommands];
742
- host.slashCommands.registerAll(cmds, owner);
743
- for (const c of cmds)
744
- registeredCommandNames.push(owner === "core" ? c.name : `${owner}:${c.name}`);
745
- }
746
- if (pack.extensions && host.extensions) {
747
- for (const ext of pack.extensions) {
748
- unregisterExtensions.push(host.extensions.register(ext));
748
+ const rollback = () => {
749
+ for (let i = unregisterExtensions.length - 1; i >= 0; i--) {
750
+ unregisterExtensions[i]();
749
751
  }
750
- }
751
- if (pack.setup) {
752
- if (!opts.api) {
753
- throw new Error(`Pack "${pack.name}" defines setup() but no PluginAPI was provided`);
752
+ for (let i = registeredCommandNames.length - 1; i >= 0; i--) {
753
+ host.slashCommands.unregister(registeredCommandNames[i]);
754
754
  }
755
- try {
756
- await pack.setup(opts.api);
757
- } catch (setupErr) {
758
- for (let i = unregisterExtensions.length - 1; i >= 0; i--) {
759
- unregisterExtensions[i]();
755
+ for (let i = registeredToolNames.length - 1; i >= 0; i--) {
756
+ host.tools.unregister(registeredToolNames[i]);
757
+ }
758
+ for (let i = registeredProviderTypes.length - 1; i >= 0; i--) {
759
+ host.providers.unregister(registeredProviderTypes[i]);
760
+ }
761
+ };
762
+ try {
763
+ if (pack.tools) {
764
+ for (const t of pack.tools) {
765
+ host.tools.register(t, owner);
766
+ registeredToolNames.push(t.name);
760
767
  }
761
- for (let i = registeredCommandNames.length - 1; i >= 0; i--) {
762
- host.slashCommands.unregister(registeredCommandNames[i]);
768
+ }
769
+ if (pack.providers) {
770
+ for (const p of pack.providers) {
771
+ host.providers.register(p);
772
+ registeredProviderTypes.push(p.type);
773
+ }
774
+ }
775
+ if (pack.slashCommands) {
776
+ for (const c of pack.slashCommands) {
777
+ host.slashCommands.register(c, owner);
778
+ registeredCommandNames.push(owner === "core" ? c.name : `${owner}:${c.name}`);
763
779
  }
764
- for (let i = registeredToolNames.length - 1; i >= 0; i--) {
765
- host.tools.unregister(registeredToolNames[i]);
780
+ }
781
+ if (pack.extensions && host.extensions) {
782
+ for (const ext of pack.extensions) {
783
+ unregisterExtensions.push(host.extensions.register(ext));
766
784
  }
767
- for (let i = registeredProviderTypes.length - 1; i >= 0; i--) {
768
- host.providers.unregister(registeredProviderTypes[i]);
785
+ }
786
+ if (pack.setup) {
787
+ if (!opts.api) {
788
+ throw new Error(`Pack "${pack.name}" defines setup() but no PluginAPI was provided`);
769
789
  }
770
- throw setupErr;
790
+ await pack.setup(opts.api);
771
791
  }
792
+ } catch (mountErr) {
793
+ rollback();
794
+ throw mountErr;
772
795
  }
773
796
  return {
774
797
  pack,
775
798
  owner,
776
799
  async teardown() {
777
- for (let i = unregisterExtensions.length - 1; i >= 0; i--) {
778
- unregisterExtensions[i]();
779
- }
780
- for (let i = registeredCommandNames.length - 1; i >= 0; i--) {
781
- host.slashCommands.unregister(registeredCommandNames[i]);
782
- }
783
- for (let i = registeredToolNames.length - 1; i >= 0; i--) {
784
- host.tools.unregister(registeredToolNames[i]);
785
- }
786
- for (let i = registeredProviderTypes.length - 1; i >= 0; i--) {
787
- host.providers.unregister(registeredProviderTypes[i]);
788
- }
800
+ rollback();
789
801
  if (pack.teardown) {
790
802
  if (!opts.api) {
791
803
  throw new Error(`Pack "${pack.name}" defines teardown() but no PluginAPI was provided`);
@@ -1028,7 +1040,6 @@ async function routeImagesForModel(blocks, opts) {
1028
1040
  }
1029
1041
  const out = [];
1030
1042
  let convertedImages = 0;
1031
- let lastErr;
1032
1043
  let adapterName;
1033
1044
  for (const block of blocks) {
1034
1045
  if (block.type !== "image") {
@@ -1036,14 +1047,17 @@ async function routeImagesForModel(blocks, opts) {
1036
1047
  continue;
1037
1048
  }
1038
1049
  let description;
1050
+ let lastErr;
1039
1051
  for (const adapter of adapters) {
1040
1052
  try {
1041
- description = await adapter.describe({
1053
+ const candidate = await adapter.describe({
1042
1054
  image: block,
1043
1055
  prompt: opts.prompt,
1044
1056
  ctx: opts.ctx,
1045
1057
  signal: opts.signal
1046
1058
  });
1059
+ if (!candidate?.trim()) continue;
1060
+ description = candidate;
1047
1061
  adapterName = adapter.name;
1048
1062
  break;
1049
1063
  } catch (err) {
package/dist/vision.js CHANGED
@@ -48,7 +48,6 @@ async function routeImagesForModel(blocks, opts) {
48
48
  }
49
49
  const out = [];
50
50
  let convertedImages = 0;
51
- let lastErr;
52
51
  let adapterName;
53
52
  for (const block of blocks) {
54
53
  if (block.type !== "image") {
@@ -56,14 +55,17 @@ async function routeImagesForModel(blocks, opts) {
56
55
  continue;
57
56
  }
58
57
  let description;
58
+ let lastErr;
59
59
  for (const adapter of adapters) {
60
60
  try {
61
- description = await adapter.describe({
61
+ const candidate = await adapter.describe({
62
62
  image: block,
63
63
  prompt: opts.prompt,
64
64
  ctx: opts.ctx,
65
65
  signal: opts.signal
66
66
  });
67
+ if (!candidate?.trim()) continue;
68
+ description = candidate;
67
69
  adapterName = adapter.name;
68
70
  break;
69
71
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wrongstack/runtime",
3
- "version": "0.319.0",
3
+ "version": "1.0.0",
4
4
  "license": "MIT",
5
5
  "description": "WrongStack default runtime implementations and host-level composition helpers built on @wrongstack/core.",
6
6
  "repository": {
@@ -64,16 +64,16 @@
64
64
  "README.md"
65
65
  ],
66
66
  "dependencies": {
67
- "@wrongstack/core": "0.319.0",
68
- "@wrongstack/kanban": "0.319.0",
69
- "@wrongstack/governance": "0.319.0",
70
- "@wrongstack/sage": "0.319.0",
71
- "@wrongstack/tools": "0.319.0",
72
- "@wrongstack/vector-memory": "0.319.0"
67
+ "@wrongstack/core": "1.0.0",
68
+ "@wrongstack/kanban": "1.0.0",
69
+ "@wrongstack/governance": "1.0.0",
70
+ "@wrongstack/sage": "1.0.0",
71
+ "@wrongstack/tools": "1.0.0",
72
+ "@wrongstack/vector-memory": "1.0.0"
73
73
  },
74
74
  "devDependencies": {
75
75
  "@types/node": "^26.2.0",
76
- "@wrongstack/wrongtrace": "0.319.0",
76
+ "@wrongstack/wrongtrace": "1.0.0",
77
77
  "typescript": "^7.0.2"
78
78
  },
79
79
  "publishConfig": {