@quantiya/codevibe-claude-plugin 2.0.32 → 2.0.33

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.
@@ -21,8 +21,23 @@ export declare const COMPACTION_KEEP_HOT_RECENT_ITEMS = 16;
21
21
  * hosted 7-day session TTL; chosen here (design leaves the number open).
22
22
  */
23
23
  export declare const CONTEXT_ITEMS_RETENTION_MS: number;
24
- /** The rendered session-context section's own budget (inside the F6 total). */
24
+ /**
25
+ * The rendered session-context section's own budget (inside the F6 total) for
26
+ * the implementor dispatch block and the brainstorm panel: 2,000 chars, every
27
+ * line capped by `capForRender`, stop at the first line that does not fit — the
28
+ * shipped behaviour. The planner's classification render uses
29
+ * `SESSION_CONTEXT_SECTION_MAX_CHARS_CLASSIFY` below (Stage-1 r1 F5 / r2 F2,
30
+ * 2026-09-12).
31
+ */
25
32
  export declare const SESSION_CONTEXT_SECTION_MAX_CHARS = 2000;
33
+ /**
34
+ * The planner's CLASSIFICATION render (2026-09-12): hot turns render WHOLE inside
35
+ * a 6,000-char section under the local runner's explicit 16K-token window.
36
+ * Stage-1 r1 F5 — this applies ONLY to `purpose: 'classification'`: the implementor
37
+ * dispatch block (hard 4,800-char total, `DISPATCH_CONTEXT_MAX_CHARS`) and the
38
+ * brainstorm panel keep the 2,000-char section and the per-line cap above.
39
+ */
40
+ export declare const SESSION_CONTEXT_SECTION_MAX_CHARS_CLASSIFY = 6000;
26
41
  /**
27
42
  * A1f Stage-1 R1 HIGH + Stage-2 R1 (H1/M2/M3/M5) — one distilled FACT:
28
43
  * - `body` — the source item's COMPLETE typed payload, verbatim (M3:
@@ -136,6 +151,13 @@ export declare function compactionCachePath(sessionId: string): string;
136
151
  * hot view). Never throws.
137
152
  */
138
153
  export declare function loadCompactionCache(sessionId: string): Promise<SessionCompactionCache>;
154
+ /**
155
+ * Stage-1 r1 F4 — an ends-preserving cut for the ONE line that must survive even
156
+ * when it exceeds the section (the newest hot item): the head carries the referent,
157
+ * the tail the latest words, and the marker makes the cut visible to the model.
158
+ */
159
+ export declare const RENDER_CUT_MARKER = " [\u2026] ";
160
+ export declare function cutPreservingEnds(text: string, max: number): string;
139
161
  /**
140
162
  * Stage-2 R1 H1 — the dispatch-scope predicate, applied IDENTICALLY to hot
141
163
  * items and distilled facts (composes WITH the §5 label floor, never
@@ -0,0 +1,28 @@
1
+ export type DestructiveRequestMatch = {
2
+ kind: 'none';
3
+ }
4
+ /** One named file is the whole object of the deletion. */
5
+ | {
6
+ kind: 'target';
7
+ target: string;
8
+ }
9
+ /** A deletion of several / located / unnamed files — the question quotes the request. */
10
+ | {
11
+ kind: 'neutral';
12
+ };
13
+ /** Classify `text` against the backstop's shapes (see the module comment). */
14
+ export declare function matchDestructiveFileRequest(text: string): DestructiveRequestMatch;
15
+ /**
16
+ * True when `text` asks to delete / remove a named file or a file/folder object.
17
+ * A conservative shape matcher (a backstop, not a classifier): false for edits
18
+ * that only mention a file or removal inside a file.
19
+ */
20
+ export declare function isDestructiveFileRequest(text: string): boolean;
21
+ /** The file the request names as the WHOLE object of the deletion, when there is exactly that. */
22
+ export declare function destructiveRequestTarget(text: string): string | undefined;
23
+ /**
24
+ * The confirmation the classifier should have asked (P43 shape: target-specific
25
+ * when one named file is the whole object, otherwise quoting the request), ending
26
+ * with the yes/no instruction the answered round relies on.
27
+ */
28
+ export declare function destructiveConfirmationQuestion(text: string): string;
@@ -2,6 +2,7 @@ import { AsyncLocalStorage } from 'node:async_hooks';
2
2
  import { AppSyncClient } from '../appsync';
3
3
  import { Session } from '../types';
4
4
  import { OrchestrationStore } from './store';
5
+ import { type RetainedBrowsePage } from './route-browse';
5
6
  /**
6
7
  * WEB-BROWSING-DESIGN.md rev 6 — the address for a model-chosen fetch.
7
8
  *
@@ -780,6 +781,12 @@ export declare function routeAdvisory(deps: {
780
781
  * image couldn't be used instead of answering as if none was attached.
781
782
  */
782
783
  attemptedImages?: number;
784
+ /**
785
+ * 2026-09-12 — the page the `browse` route read most recently in this session.
786
+ * Rendered as untrusted source material the model uses ONLY when the request is
787
+ * about that page (the model decides relevance, the shell does not).
788
+ */
789
+ retainedPage?: RetainedBrowsePage;
783
790
  }): Promise<void>;
784
791
  export declare function parseTeamWorkItems(rawArg: string): {
785
792
  ok: true;
@@ -986,6 +993,8 @@ export declare function tokenizeCommandLine(input: string): {
986
993
  error?: string;
987
994
  };
988
995
  export declare function handleShellUserInput(deps: HandleShellUserInputDeps): Promise<void>;
996
+ /** Test seam — clear the per-session retained pages between cases. */
997
+ export declare function resetRetainedBrowsePagesForTests(): void;
989
998
  /**
990
999
  * [A1g] Stage-2 round-4 (Codex round-3 MEDIUM) — the EXPLICIT per-turn panel-
991
1000
  * ownership token. `serializeShellSubmissions` mints ONE fresh object per
@@ -1,5 +1,19 @@
1
1
  import type { OrchestrationStore } from './store';
2
2
  import type { LocalGemmaAdvisoryRunner } from '../planner/local-advisory';
3
+ /**
4
+ * A page the shell read this session, retained (2026-09-12) so a follow-up
5
+ * ("that sounds like a summary, I am looking for your thoughts") can be answered
6
+ * by the local model WITH the page in front of it instead of from a three-sentence
7
+ * summary — or a re-fetch. Text is already terminal-sanitized and bounded.
8
+ */
9
+ export interface RetainedBrowsePage {
10
+ url: string;
11
+ title: string;
12
+ text: string;
13
+ readAt: string;
14
+ }
15
+ /** Retained page text bound — the answerer caps again at render time. */
16
+ export declare const RETAINED_PAGE_MAX_CHARS = 24000;
3
17
  export interface RouteBrowseDeps {
4
18
  store: OrchestrationStore;
5
19
  /** Undefined when the local model isn't installed/enabled → no-model advisory. */
@@ -11,6 +25,8 @@ export interface RouteBrowseDeps {
11
25
  priorTurns?: string[];
12
26
  /** Esc-abort signal (shell-owned AbortController). */
13
27
  signal?: AbortSignal;
28
+ /** Called once readable text was extracted from a fetched page (before summarizing). */
29
+ onPageRead?: (page: RetainedBrowsePage) => void;
14
30
  }
15
31
  /**
16
32
  * Orchestrate a `browse` route. Fetch an explicit URL, or run a keyless web
@@ -39,37 +39,67 @@ export declare class PlannerOutputUnparseableError extends Error {
39
39
  * to diagnose. Absent when the error was raised without a raw string in hand.
40
40
  */
41
41
  rawOutputHead?: string;
42
- constructor(message: string);
42
+ /**
43
+ * Design §7 R3 (restored 2026-09-12 after the dogfood follow-up incident):
44
+ * `'parse'` — the model's text never became a JSON object (prose, truncated or
45
+ * conflicting output); `'validation'` — a JSON object with a recognised `action`
46
+ * was produced but a per-action key rule or the schema rejected it. The shell
47
+ * fails closed on the first class and may degrade the second to the safe
48
+ * advisory route when {@link degradeTo} names an answer-type intent.
49
+ */
50
+ readonly kind: 'parse' | 'validation';
51
+ /**
52
+ * The rejected decision's ANSWER-TYPE intent — `advisory_response` / `brainstorm`
53
+ * (answered through the local advisory route) or `refuse` (rendered as the
54
+ * shell's deterministic refusal with this rationale) — plus whatever user-facing
55
+ * text it carried. NEVER set for `start_task` / `team_decompose` / `browse` (a
56
+ * broken decision must never start work or fetch anything), nor for `ask_user` /
57
+ * `familiarize` (Stage-1 r1 F2: those fail closed).
58
+ */
59
+ readonly degradeTo?: {
60
+ action: PlannerDecision['action'];
61
+ rationale?: string;
62
+ advisorySummary?: string;
63
+ };
64
+ constructor(message: string, options?: {
65
+ kind?: 'parse' | 'validation';
66
+ degradeTo?: PlannerOutputUnparseableError['degradeTo'];
67
+ });
43
68
  }
44
- export declare const LOCAL_GEMMA_DECISION_JSON_SCHEMA: {
45
- type: string;
69
+ export declare function localGemmaAllowedActions(isSubprocessRunner: boolean): ReadonlySet<PlannerDecision['action']>;
70
+ interface LocalGemmaDecisionJsonSchema {
71
+ type: 'object';
46
72
  properties: {
47
73
  rationale: {
48
- type: string;
74
+ type: 'string';
49
75
  };
50
76
  clarifying_question: {
51
- type: string;
77
+ type: 'string';
52
78
  };
53
79
  advisory_summary: {
54
- type: string;
80
+ type: 'string';
55
81
  };
56
82
  browseUrls: {
57
- type: string;
83
+ type: 'array';
58
84
  items: {
59
- type: string;
85
+ type: 'string';
60
86
  };
61
87
  };
62
88
  browseQuery: {
63
- type: string;
89
+ type: 'string';
64
90
  };
65
91
  action: {
66
- type: string;
67
- enum: ("start_task" | "summarize_current_status" | "advisory_response" | "ask_user" | "refuse" | "team_decompose" | "familiarize" | "brainstorm" | "browse")[];
92
+ type: 'string';
93
+ enum: PlannerDecision['action'][];
68
94
  };
69
95
  };
70
96
  required: string[];
71
97
  additionalProperties: boolean;
72
- };
98
+ }
99
+ /** The Ollama runner's schema (no `summarize_current_status`). */
100
+ export declare const LOCAL_GEMMA_DECISION_JSON_SCHEMA: LocalGemmaDecisionJsonSchema;
101
+ /** The subprocess runner's schema keeps `summarize_current_status` (Stage-2 codex R1-F3). */
102
+ export declare const LOCAL_GEMMA_SUBPROCESS_DECISION_JSON_SCHEMA: LocalGemmaDecisionJsonSchema;
73
103
  /**
74
104
  * Text-only route classifier prompt. It intentionally excludes repository
75
105
  * paths, summaries, source snippets, file bodies, and the raw structural digest.
@@ -81,7 +111,9 @@ export declare function renderLocalGemmaPlannerPrompt(input: PlannerInput, optio
81
111
  export declare const RAW_OUTPUT_HEAD_CHARS = 500;
82
112
  /** Terminal-control-free, bounded head of a raw model output for the warn log. */
83
113
  export declare function summarizeRawOutputForLog(raw: string): string;
84
- export declare function parseLocalGemmaPlannerDecision(raw: string): PlannerDecision;
114
+ export declare function parseLocalGemmaPlannerDecision(raw: string, options?: {
115
+ isSubprocessRunner?: boolean;
116
+ }): PlannerDecision;
85
117
  export declare class LocalGemmaPlannerAdapter implements PlannerAdapter {
86
118
  private readonly runner;
87
119
  private activeSessionId;
@@ -90,3 +122,4 @@ export declare class LocalGemmaPlannerAdapter implements PlannerAdapter {
90
122
  probe(): Promise<PlannerProbeResult>;
91
123
  setActiveSession(sessionId: string | null): void;
92
124
  }
125
+ export {};
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-core",
3
- "version": "2.0.27",
3
+ "version": "2.0.28",
4
4
  "description": "Core library for CodeVibe plugins - shared keychain, crypto, AppSync, and auth functionality",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-claude-plugin",
3
- "version": "2.0.32",
3
+ "version": "2.0.33",
4
4
  "description": "Control Claude Code from your iPhone and Android — real-time sync, approve file edits, send prompts by voice. Part of CodeVibe.",
5
5
  "main": "dist/server.js",
6
6
  "codevibe": {
@@ -48,7 +48,7 @@
48
48
  "node": ">=22.0.0"
49
49
  },
50
50
  "dependencies": {
51
- "@quantiya/codevibe-core": "^2.0.27",
51
+ "@quantiya/codevibe-core": "^2.0.28",
52
52
  "@quantiya/quorum-core": "^1.0.1",
53
53
  "dotenv": "^16.6.1",
54
54
  "express": "^5.1.0",