pi-roundtable-sandbox 0.7.4 → 0.7.5

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.5
4
+
5
+ - `ScopedSandboxDelegator` limits a title to 200 characters by default again, and accepts `maxTitleChars`, `maxReportChars` and `diagnosticChars`.
6
+
3
7
  ## 0.7.4
4
8
 
5
9
  - Let `SandboxResearchWorker` run the host's own web tools (`tools`, `scope`, `aborted`), and make `ScopedSandboxDelegator` refuse and fail with readable reasons (scrubbed) instead of generic text, with no title limit.
package/README.md CHANGED
@@ -316,6 +316,7 @@ Its default limit is two jobs per channel, 4,000 task characters, 80,000 report
316
316
  A refusal reads "title and task are required", "the task is N characters; keep it within 4000" or "this channel already has N delegated tasks running; wait for one to report back".
317
317
  A failed job reports its error message scrubbed of credentials and bounded with `scrubDiagnostic`, or "the worker ran out of time" after the deadline.
318
318
  Configure `maxRunning` (1–10) and `timeoutMs` (1–1,200 seconds) explicitly when preserving an application's existing limits.
319
+ A title is limited to 200 characters; `maxTitleChars` changes that, `maxReportChars` replaces the 80,000-character report bound and `diagnosticChars` the 600-character failure reason (each a whole number of at least 1, or `Infinity`).
319
320
  `run(task, context)` receives only bound channel/author/signal, and `deliver(job, result)` posts through the application's background-report adapter.
320
321
  `runningChannels`, `idle` and `dispose` support host lifecycle handling; jobs are process-local and are cancelled on disposal.
321
322
  `SandboxResearchWorker` is an optional host subscription adapter with explicit `modelRuntime`, `agentDir`, `workDir`, `model`, `thinking`, `search`, and `extractFetched` options.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-roundtable-sandbox",
3
- "version": "0.7.4",
3
+ "version": "0.7.5",
4
4
  "description": "Sealed guest channels and an allow-listed credential broker for pi-roundtable",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -52,7 +52,7 @@
52
52
  "@biomejs/biome": "2.5.15",
53
53
  "@types/bun": "1.4.2",
54
54
  "discord.js": "14.27.0",
55
- "pi-roundtable": "0.7.4",
55
+ "pi-roundtable": "0.7.5",
56
56
  "typebox": "1.3.34",
57
57
  "typescript": "7.0.2"
58
58
  }
@@ -8,11 +8,18 @@ import { DelegationError } from "pi-roundtable";
8
8
  import { scrubDiagnostic } from "pi-roundtable/kit";
9
9
 
10
10
  const MAX_TASK_CHARS = 4_000;
11
+ const MAX_TITLE_CHARS = 200;
11
12
 
12
13
  export interface ScopedDelegatorOptions {
13
14
  target: string;
14
15
  maxRunning?: number;
15
16
  timeoutMs?: number;
17
+ /** Longest title, in characters; default 200. A host whose callers already send longer ones raises it. */
18
+ maxTitleChars?: number;
19
+ /** Longest research report, in characters, or `Infinity`; default 80,000. */
20
+ maxReportChars?: number;
21
+ /** Longest failure reason kept, in characters, or `Infinity`; default 600. */
22
+ diagnosticChars?: number;
16
23
  run(
17
24
  task: string,
18
25
  context: {
@@ -44,6 +51,24 @@ export class ScopedSandboxDelegator {
44
51
  (options.timeoutMs ?? 600_000) > 1_200_000
45
52
  )
46
53
  throw new Error("Invalid delegation target/budget");
54
+ if (
55
+ options.maxTitleChars !== undefined &&
56
+ !Number.isSafeInteger(options.maxTitleChars) &&
57
+ options.maxTitleChars !== Number.POSITIVE_INFINITY
58
+ )
59
+ throw new Error("Invalid delegation title limit");
60
+ if (options.maxTitleChars !== undefined && options.maxTitleChars < 1)
61
+ throw new Error("Invalid delegation title limit");
62
+ for (const [name, value] of [
63
+ ["maxReportChars", options.maxReportChars],
64
+ ["diagnosticChars", options.diagnosticChars],
65
+ ] as const)
66
+ if (
67
+ value !== undefined &&
68
+ value !== Number.POSITIVE_INFINITY &&
69
+ (!Number.isSafeInteger(value) || value < 1)
70
+ )
71
+ throw new Error(`Invalid delegation ${name}`);
47
72
  this.#options = options;
48
73
  }
49
74
  start(
@@ -59,6 +84,11 @@ export class ScopedSandboxDelegator {
59
84
  const task = request.task.trim();
60
85
  if (!request.title.trim() || !task)
61
86
  throw new DelegationError("title and task are required");
87
+ const maxTitle = this.#options.maxTitleChars ?? MAX_TITLE_CHARS;
88
+ if (request.title.length > maxTitle)
89
+ throw new DelegationError(
90
+ `the title is ${request.title.length} characters; keep it within ${maxTitle}`,
91
+ );
62
92
  if (task.length > MAX_TASK_CHARS)
63
93
  throw new DelegationError(
64
94
  `the task is ${task.length} characters; keep it within ${MAX_TASK_CHARS}`,
@@ -93,7 +123,10 @@ export class ScopedSandboxDelegator {
93
123
  signal,
94
124
  });
95
125
  signal.throwIfAborted();
96
- if (typeof report !== "string" || report.length > 80_000)
126
+ if (
127
+ typeof report !== "string" ||
128
+ report.length > (this.#options.maxReportChars ?? 80_000)
129
+ )
97
130
  throw new Error("Research report too large");
98
131
  result = { ok: true, report };
99
132
  } catch (error) {
@@ -102,6 +135,7 @@ export class ScopedSandboxDelegator {
102
135
  ? "the worker ran out of time"
103
136
  : scrubDiagnostic(
104
137
  error instanceof Error ? error.message : String(error),
138
+ this.#options.diagnosticChars,
105
139
  );
106
140
  result = { ok: false, error: reason || "the task failed" };
107
141
  }