@hypercarrier/rarebit 0.1.0-alpha.6 → 0.2.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/src/types.d.ts CHANGED
@@ -1,5 +1,47 @@
1
1
  export type RarebitModel = { provider: string; id: string };
2
2
 
3
+ export type RarebitDiagnosticsSettings = {
4
+ summaryTriggered: boolean;
5
+ summaryUpdated: boolean;
6
+ };
7
+ export type RarebitRecapSettings = {
8
+ enabled: boolean;
9
+ delayMs: number;
10
+ timezone: string;
11
+ };
12
+ export type RarebitResolvedSettings = {
13
+ model?: RarebitModel;
14
+ modelConfigurationError?: string;
15
+ summaryPolicy: RarebitSummaryPolicy;
16
+ autoTitle: boolean;
17
+ summaryPrompt?: unknown;
18
+ maxInputTokens: number;
19
+ diagnostics: RarebitDiagnosticsSettings;
20
+ recap: RarebitRecapSettings;
21
+ };
22
+ export const DEFAULT_RAREBIT_RECAP_DELAY_MS: 60000;
23
+ export const DEFAULT_RAREBIT_RECAP_TIMEZONE: "host";
24
+ export const DEFAULT_RAREBIT_MAX_INPUT_TOKENS: 64000;
25
+ export const MAX_RAREBIT_INPUT_TOKENS: number;
26
+ export const DEFAULT_RAREBIT_DIAGNOSTICS: Readonly<RarebitDiagnosticsSettings>;
27
+ export const RAREBIT_SUMMARY_PROMPT_IDENTITY_VERSION: "rarebit-summary-prompt-v1";
28
+ export const MAX_RAREBIT_SUMMARY_PROMPT_CHARS: 64000;
29
+ export const DEFAULT_RAREBIT_SUMMARY_PROMPT_GUIDANCE: string;
30
+ export const MAX_RAREBIT_SUMMARY_CHARS: 8000;
31
+ export function normalizeRarebitSummaryPrompt(value?: unknown): {
32
+ guidance: string;
33
+ promptIdentity: string | null;
34
+ };
35
+ export function mergeRarebitSettings(
36
+ globalSettings?: Record<string, unknown>,
37
+ projectSettings?: Record<string, unknown>,
38
+ ): Record<string, unknown>;
39
+ export function normalizeRarebitRecapTimezone(value?: unknown): string;
40
+ export function resolveRarebitSettings(
41
+ globalSettings?: Record<string, unknown>,
42
+ projectSettings?: Record<string, unknown>,
43
+ ): RarebitResolvedSettings;
44
+
3
45
  /** Seeded destination entries, including the generated fork notice. */
4
46
  export function getImportedRarebitEntryIds(entries: readonly unknown[]): Set<string>;
5
47
  export const RAREBIT_FORK_LINEAGE_SCHEMA_VERSION: 1;
@@ -227,14 +269,20 @@ export function composeRarebitSummaryDerivationInput(
227
269
  selection: ReturnType<typeof selectRarebits>,
228
270
  options?: {
229
271
  promptVersion?: string;
272
+ summaryPrompt?: unknown;
230
273
  lifecycleBoundary?: "owner_request" | "agent_settled" | "manual";
231
274
  maxPromptChars?: number;
232
- },
233
- ): { prompt: string; coverage: RarebitSummaryInputCoverage };
275
+ }): {
276
+ prompt: string;
277
+ promptIdentity: string | null;
278
+ promptVersion: string;
279
+ coverage: RarebitSummaryInputCoverage;
280
+ };
234
281
  export function composeRarebitSummaryPrompt(
235
282
  selection: ReturnType<typeof selectRarebits>,
236
283
  options?: {
237
284
  promptVersion?: string;
285
+ summaryPrompt?: unknown;
238
286
  lifecycleBoundary?: "owner_request" | "agent_settled" | "manual";
239
287
  maxPromptChars?: number;
240
288
  },
@@ -242,7 +290,10 @@ export function composeRarebitSummaryPrompt(
242
290
  export function composeRarebitTitlePrompt(
243
291
  selection: ReturnType<typeof selectRarebits>,
244
292
  ): string;
245
- export function normalizeRarebitSummary(value: unknown): string;
293
+ export function normalizeRarebitSummary(
294
+ value: unknown,
295
+ options?: { maxChars?: number },
296
+ ): string;
246
297
  export function normalizeRarebitSummarySynthesis(
247
298
  value: unknown,
248
299
  options?: { maxChars?: number },
@@ -395,11 +446,17 @@ export type RarebitNativeObservation =
395
446
 
396
447
  export const RAREBIT_SUMMARY_SCHEMA_VERSION: 4;
397
448
  export const RAREBIT_SUMMARY_IMPLEMENTATION_VERSION: "hc-rarebit-summary-v6";
449
+ export const RAREBIT_INPUT_CHARS_PER_TOKEN: 4;
450
+ export const DEFAULT_RAREBIT_MAX_PROMPT_CHARS: 256000;
398
451
  export function processRarebitSummary(
399
452
  ctx: unknown,
400
453
  config?: {
401
454
  model?: RarebitModel;
402
455
  summaryPolicy?: RarebitSummaryPolicy;
456
+ summaryPrompt?: unknown;
457
+ maxInputTokens?: number;
458
+ maxPromptChars?: number;
459
+ diagnostics?: RarebitDiagnosticsSettings;
403
460
  forceSynthesis?: boolean;
404
461
  // New derivation accepts only evidence-transition or explicit boundaries;
405
462
  // RarebitSummaryReceiptV4 retains session_start for historical reads.
@@ -532,6 +532,7 @@ test("TUI notices state input cardinality, clearly estimated trigger tokens, and
532
532
  rarebitRoot: join(root, "rarebit"),
533
533
  summaryPolicy: { minTotalLength: 0, maxRarebitRatio: 1 },
534
534
  model: { provider: "test-provider", id: "cheap-model" },
535
+ diagnostics: { summaryTriggered: true, summaryUpdated: true },
535
536
  modelClient: {
536
537
  complete: async () => ({
537
538
  text: JSON.stringify({
@@ -588,6 +589,7 @@ test("updated notice never substitutes the local estimate for absent provider us
588
589
  rarebitRoot: join(root, "rarebit"),
589
590
  summaryPolicy: { minTotalLength: 0, maxRarebitRatio: 1 },
590
591
  model: { provider: "requested-provider", id: "requested-model" },
592
+ diagnostics: { summaryTriggered: true, summaryUpdated: true },
591
593
  modelClient: {
592
594
  complete: async () => ({
593
595
  text: JSON.stringify({
@@ -0,0 +1,54 @@
1
+ import test from "node:test";
2
+ import assert from "node:assert/strict";
3
+ import { execFileSync, spawnSync } from "node:child_process";
4
+ import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
5
+ import { tmpdir } from "node:os";
6
+ import { join, resolve } from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+
9
+ const root = resolve(fileURLToPath(new URL("..", import.meta.url)));
10
+ const verifier = join(root, "scripts/verify-package.mjs");
11
+
12
+ function syntheticTarball(field, value) {
13
+ const work = mkdtempSync(join(tmpdir(), "rarebit-artifact-test-"));
14
+ const packageDir = join(work, "package");
15
+ execFileSync("mkdir", ["-p", packageDir]);
16
+ const packageJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
17
+ packageJson[field] = value;
18
+ writeFileSync(join(packageDir, "package.json"), `${JSON.stringify(packageJson)}\n`);
19
+ const tarball = join(work, `${field}.tgz`);
20
+ execFileSync("tar", ["-czf", tarball, "-C", work, "package"]);
21
+ return { work, tarball };
22
+ }
23
+
24
+ function runVerifier(tarball) {
25
+ return spawnSync(process.execPath, [verifier], {
26
+ cwd: root,
27
+ env: { ...process.env, RELEASE_TARBALL: tarball },
28
+ encoding: "utf8",
29
+ });
30
+ }
31
+
32
+ test("rejects packed name and version changes against selected source", () => {
33
+ for (const [field, value] of [["name", "invalid-name"], ["version", "0.0.0-invalid-test"]]) {
34
+ const fixture = syntheticTarball(field, value);
35
+ try {
36
+ const result = runVerifier(fixture.tarball);
37
+ assert.notEqual(result.status, 0, `${field} mutation was accepted`);
38
+ assert.match(`${result.stdout}\n${result.stderr}`, /packed package (name|version) differs from selected source/);
39
+ } finally {
40
+ rmSync(fixture.work, { recursive: true, force: true });
41
+ }
42
+ }
43
+ });
44
+
45
+ test("accepts the normal packed artifact", () => {
46
+ const filename = JSON.parse(execFileSync("npm", ["pack", "--json", "--ignore-scripts"], { cwd: root, encoding: "utf8" }))[0].filename;
47
+ const tarball = join(root, filename);
48
+ try {
49
+ const result = runVerifier(tarball);
50
+ assert.equal(result.status, 0, result.stderr);
51
+ } finally {
52
+ rmSync(tarball, { force: true });
53
+ }
54
+ });
@@ -14,11 +14,11 @@ const values = (prefix) =>
14
14
  test("one grammar derives command description and usage", () => {
15
15
  assert.equal(
16
16
  rarebitCommandDescription(),
17
- "Rarebit status/recall/fork/config/auto-title/title/summarize",
17
+ "Rarebit menu/settings/help/status/recall/fork/config/auto-title/title/recap/summarize",
18
18
  );
19
19
  assert.equal(
20
20
  rarebitCommandUsage(),
21
- "Usage: /rarebit [status|recall|fork|config|auto-title|title|summarize]",
21
+ "Usage: /rarebit [menu|settings|help|status|recall|fork|config|auto-title|title|recap|summarize]",
22
22
  );
23
23
  assert.equal(
24
24
  rarebitCommandUsage("config"),
@@ -41,7 +41,7 @@ test("one grammar derives command description and usage", () => {
41
41
  test("parser accepts exactly the command grammar", () => {
42
42
  assert.deepEqual(parseRarebitCommand(""), {
43
43
  ok: true,
44
- subcommand: "status",
44
+ subcommand: "menu",
45
45
  arguments: [],
46
46
  });
47
47
  assert.equal(parseRarebitCommand("fork").ok, true);
@@ -93,15 +93,19 @@ test("parser accepts exactly the command grammar", () => {
93
93
 
94
94
  test("autocomplete covers subcommands and discrete nested arguments", () => {
95
95
  assert.deepEqual(values(""), [
96
+ "menu",
97
+ "settings",
98
+ "help",
96
99
  "status",
97
100
  "recall",
98
101
  "fork",
99
102
  "config",
100
103
  "auto-title",
101
104
  "title",
105
+ "recap",
102
106
  "summarize",
103
107
  ]);
104
- assert.deepEqual(values("s"), ["status", "summarize"]);
108
+ assert.deepEqual(values("s"), ["settings", "status", "summarize"]);
105
109
  assert.deepEqual(values("config "), [
106
110
  "config max_rarebit_ratio ",
107
111
  "config min_total_length ",