@quantiya/codevibe-claude-plugin 2.0.33 → 2.0.35

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.
Files changed (19) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/node_modules/@quantiya/codevibe-core/dist/index.d.ts +2 -1
  3. package/node_modules/@quantiya/codevibe-core/dist/index.js +453 -421
  4. package/node_modules/@quantiya/codevibe-core/dist/local-model/ollama.d.ts +2 -0
  5. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/__tests__/route-browse-multi-result.test.d.ts +1 -0
  6. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/__tests__/runOrchestrationShell-browse-cancel.test.d.ts +1 -0
  7. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/cli.js +895 -74
  8. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/components/InputBar.d.ts +5 -0
  9. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/components/OrchestrationApp.d.ts +5 -0
  10. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/index.d.ts +5 -0
  11. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/route-browse.d.ts +8 -2
  12. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/web/extract.d.ts +18 -0
  13. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/web/fetch.d.ts +5 -1
  14. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/web/search.d.ts +32 -3
  15. package/node_modules/@quantiya/codevibe-core/dist/orchestration-shell/workspace-terminal-coordinator.d.ts +2 -0
  16. package/node_modules/@quantiya/codevibe-core/dist/planner/index.d.ts +1 -1
  17. package/node_modules/@quantiya/codevibe-core/dist/planner/local-advisory.d.ts +60 -1
  18. package/node_modules/@quantiya/codevibe-core/package.json +1 -1
  19. package/package.json +12 -3
@@ -124,5 +124,10 @@ export interface InputBarProps {
124
124
  * `@all` plus the local agents detected for this signed-in user/device.
125
125
  */
126
126
  mentionSuggestions?: MentionSuggestion[];
127
+ /**
128
+ * Cancellation callback (WEB-BROWSING-DESIGN.md §Cancellation).
129
+ * Fires on Escape key when dropdown is closed and gate prompt is not active.
130
+ */
131
+ onCancel?: () => void;
127
132
  }
128
133
  export declare function InputBar(props: InputBarProps): React.ReactElement;
@@ -50,6 +50,11 @@ export interface OrchestrationAppProps {
50
50
  * #C8M-11 and never reach `onUserInput`. `images` (IMAGE-ATTACHMENT-DESIGN.md
51
51
  * §13 Option 2) carries the resolved path(s) of `[Image #N]` input chips. */
52
52
  onUserInput: (text: string, images?: string[]) => void;
53
+ /**
54
+ * Cancellation callback (WEB-BROWSING-DESIGN.md line 61).
55
+ * Forwarded to <InputBar onCancel={props.onCancel}>.
56
+ */
57
+ onCancel?: () => void;
53
58
  /**
54
59
  * CP-8 min Stage 1 R1 closure + Stage 2 r1 Codex HIGH-1 (REQUIRED). The
55
60
  * desktop-side AppSync transport surface (codevibe-core's own
@@ -265,6 +265,7 @@ export { renderEntryAsLine, runLineLogFallback } from './non-tty-fallback';
265
265
  export { initInkRuntime, getInkRuntime } from './ink-runtime';
266
266
  export { reducer } from './reducer';
267
267
  export { createOrchestrationStore, type OrchestrationStore } from './store';
268
+ export { routeBrowse, type RouteBrowseDeps } from './route-browse';
268
269
  export type { Mode, Tier, PlannerDecision, AgentKind, PlannerHealthState, RunningTaskState, ReviewerSeatState, GateState, ExecutionEventEntry, RefusalEventEntry, BypassEventEntry, MobileEventEntry, EventStreamEntry, ConversationEntry, QueuedTask, PendingClarification, OrchestrationState, OrchestrationAction, LastModeFile, TeamState, TeamTrackEntry, TeamTrackState, TeamMergeGateStatus, LiveProgress, } from './types';
269
270
  export { formatElapsed, isSpinnerPhase, renderProgressLine, type TaskProgressEvent, type OnProgress, } from './task-progress';
270
271
  export { runDeclaredTestSurfaces, DECLARED_TEST_TIMEOUT_MS, type DeclaredTestResult, type DeclaredTestReason, type RunDeclaredTestSurfacesArgs, } from './declared-test-runner';
@@ -919,6 +920,10 @@ export interface HandleShellUserInputDeps extends StructuralSummaryRunDeps {
919
920
  * buffered replies. Optional — direct unit callers/tests may omit it.
920
921
  */
921
922
  turnOwnership?: BrainstormTurnOwnership;
923
+ /**
924
+ * Optional AbortSignal for in-flight web browsing cancellation (Esc-abort).
925
+ */
926
+ browseSignal?: AbortSignal;
922
927
  }
923
928
  /**
924
929
  * Slash + natural-language dispatch. Extracted from `runOrchestrationShell`
@@ -1,5 +1,7 @@
1
1
  import type { OrchestrationStore } from './store';
2
2
  import type { LocalGemmaAdvisoryRunner } from '../planner/local-advisory';
3
+ import { guardedFetch } from './web/fetch';
4
+ import { webSearch } from './web/search';
3
5
  /**
4
6
  * A page the shell read this session, retained (2026-09-12) so a follow-up
5
7
  * ("that sounds like a summary, I am looking for your thoughts") can be answered
@@ -27,10 +29,14 @@ export interface RouteBrowseDeps {
27
29
  signal?: AbortSignal;
28
30
  /** Called once readable text was extracted from a fetched page (before summarizing). */
29
31
  onPageRead?: (page: RetainedBrowsePage) => void;
32
+ /** Dependency injection for guardedFetch (for tests / isolation). */
33
+ guardedFetchFn?: typeof guardedFetch;
34
+ /** Dependency injection for webSearch (for tests / isolation). */
35
+ webSearchFn?: typeof webSearch;
30
36
  }
31
37
  /**
32
- * Orchestrate a `browse` route. Fetch an explicit URL, or run a keyless web
33
- * search and read the top result, then answer via local Gemma. Mirrors
38
+ * Orchestrate a `browse` route. Fetch an explicit URL, or run a web
39
+ * search and read the top results in parallel, then answer via local Gemma. Mirrors
34
40
  * routeBrainstorm/routeFamiliarize (no-model advisory, clean failures, no crash).
35
41
  */
36
42
  export declare function routeBrowse(deps: RouteBrowseDeps): Promise<void>;
@@ -9,3 +9,21 @@ export declare function __resetExtractCacheForTest(): void;
9
9
  * NEVER throws — returns `{ title:'', text:'' }` on the size cap / load / parse failure.
10
10
  */
11
11
  export declare function htmlToText(html: string): Promise<ExtractResult>;
12
+ export interface ExtractQuerySnippetsOptions {
13
+ maxChars?: number;
14
+ leadChars?: number;
15
+ }
16
+ /**
17
+ * Tokenize query into search keywords (>= 3 chars for Latin/digits, >= 2 chars for CJK, plus CJK bigrams).
18
+ * Discards stopwords (Simplified + Traditional CJK and common Latin function words) and strips URLs.
19
+ */
20
+ export declare function extractQueryTokens(query: string): string[];
21
+ /**
22
+ * Extract query-relevant snippets from extracted page text.
23
+ * Always retains the lead (context / introduction, ~500 chars), plus highest-scoring
24
+ * paragraphs matching query keywords across the entire document (e.g. pricing,
25
+ * release dates, or specs at the bottom of long pages).
26
+ * Returns paragraphs stitched in original document order with `[...]` omission markers.
27
+ * NEVER throws.
28
+ */
29
+ export declare function extractQueryRelevantSnippets(fullText: string, query: string, options?: ExtractQuerySnippetsOptions): string;
@@ -8,8 +8,12 @@ export interface FetchResult {
8
8
  contentType: string;
9
9
  body: string;
10
10
  }
11
+ export interface GuardedFetchOptions {
12
+ headers?: Record<string, string>;
13
+ allowJson?: boolean;
14
+ }
11
15
  /**
12
16
  * Guarded GET with manual redirect following (full guard re-run per hop). Returns
13
17
  * decoded text or throws FetchError. `signal` lets the caller (Esc) abort.
14
18
  */
15
- export declare function guardedFetch(rawUrl: string, signal?: AbortSignal): Promise<FetchResult>;
19
+ export declare function guardedFetch(rawUrl: string, signal?: AbortSignal, options?: GuardedFetchOptions): Promise<FetchResult>;
@@ -1,6 +1,15 @@
1
1
  export interface SearchResult {
2
2
  url: string;
3
3
  title: string;
4
+ snippet?: string;
5
+ source?: 'google' | 'brave' | 'duckduckgo';
6
+ }
7
+ export interface WebSearchOptions {
8
+ limit?: number;
9
+ provider?: 'auto' | 'google' | 'brave' | 'duckduckgo';
10
+ googleApiKey?: string;
11
+ googleCx?: string;
12
+ braveApiKey?: string;
4
13
  }
5
14
  /**
6
15
  * Parse DDG HTML result anchors. DDG wraps targets as
@@ -10,7 +19,27 @@ export interface SearchResult {
10
19
  */
11
20
  export declare function parseDdgResults(html: string, limit?: number): SearchResult[];
12
21
  /**
13
- * Run a keyless web search. Returns ≤limit results, or [] on any failure
14
- * (network/parse) the caller decides the advisory. `signal` lets Esc abort.
22
+ * Query Google Custom Search JSON API when configured.
23
+ * Returns empty array on missing config or error (never throws).
24
+ */
25
+ export declare function fetchGoogleCseResults(query: string, signal?: AbortSignal, limit?: number, config?: {
26
+ apiKey?: string;
27
+ cx?: string;
28
+ }): Promise<SearchResult[]>;
29
+ /**
30
+ * Query Brave Search API when configured.
31
+ * Returns empty array on missing config or error (never throws).
32
+ */
33
+ export declare function fetchBraveSearchResults(query: string, signal?: AbortSignal, limit?: number, config?: {
34
+ apiKey?: string;
35
+ }): Promise<SearchResult[]>;
36
+ /**
37
+ * Run a multi-provider web search with waterfall fallback.
38
+ * Priority: Google CSE -> Brave API -> DuckDuckGo HTML.
39
+ * Returns ≤limit results, or [] on total failure. NEVER throws.
40
+ */
41
+ /**
42
+ * Fetch results from DuckDuckGo HTML endpoint as zero-config default.
15
43
  */
16
- export declare function webSearch(query: string, signal?: AbortSignal, limit?: number): Promise<SearchResult[]>;
44
+ export declare function fetchDuckDuckGoResults(query: string, signal?: AbortSignal, limit?: number): Promise<SearchResult[]>;
45
+ export declare function webSearch(query: string, signal?: AbortSignal, limitOrOptions?: number | WebSearchOptions): Promise<SearchResult[]>;
@@ -65,6 +65,7 @@ export declare class WorkspaceTerminalCoordinator implements WorkspaceOutcomeSin
65
65
  private readonly now;
66
66
  private readonly onSyncIssue?;
67
67
  private readonly resolutions;
68
+ private readonly reportedSyncIssues;
68
69
  private operationChain;
69
70
  constructor(options: WorkspaceTerminalCoordinatorOptions);
70
71
  private generation;
@@ -108,6 +109,7 @@ export declare class WorkspaceTerminalCoordinator implements WorkspaceOutcomeSin
108
109
  private flushTerminalIntent;
109
110
  private acknowledge;
110
111
  private quarantine;
112
+ private reportSyncIssue;
111
113
  private sendOutbox;
112
114
  /** Reconcile terminal receipts first, then replay exact encrypted bytes. */
113
115
  replayPending(): Promise<void>;
@@ -4,4 +4,4 @@ export { PlannerCacheLayer } from './cache';
4
4
  export { PlannerHealthMachine } from './health-state';
5
5
  export { BackendPlannerClient, PlannerBudgetExceededError, PlannerTierGateRejectedError, type PlannerAppSyncTransport, type PlannerCryptoBridge, type SessionKeyResolver, type ShellEventEmit, type EmitShellEventFn, } from './client';
6
6
  export { LocalGemmaPlannerAdapter, parseLocalGemmaPlannerDecision, PlannerOutputUnparseableError, renderLocalGemmaPlannerPrompt, type LocalGemmaPlannerRunner, } from './local-gemma';
7
- export { parseLocalGemmaAdvisorySummary, renderLocalGemmaFamiliarizePrompt, type LocalGemmaAdvisoryRunner, } from './local-advisory';
7
+ export { parseLocalGemmaAdvisorySummary, renderLocalGemmaFamiliarizePrompt, renderLocalGemmaMultiBrowsePrompt, renderLocalGemmaBrowsePrompt, MAX_MULTI_BROWSE_TOTAL_CONTENT_CHARS, MAX_MULTI_BROWSE_RENDERED_PROMPT_CHARS, type LocalGemmaAdvisoryRunner, } from './local-advisory';
@@ -27,12 +27,25 @@ export interface LocalGemmaAdvisoryOptions {
27
27
  * on the classifier (forced-JSON) or on `browse`/`familiarize`.
28
28
  */
29
29
  images?: string[];
30
+ /**
31
+ * Explicit context window length (tokens) for Ollama `/api/generate options.num_ctx`.
32
+ * For multi-source browsing, callers pass numCtx: 8192 to expand the active context
33
+ * window to accommodate multi-source prompts alongside output token generation.
34
+ */
35
+ numCtx?: number;
36
+ /**
37
+ * Control hidden reasoning/thinking tokens in Ollama models (e.g. Gemma 4).
38
+ * Omitted unless set; browse callers pass false (R8-F2, R9-F4).
39
+ */
40
+ think?: boolean;
30
41
  }
31
42
  export declare function redactAbsoluteLocalPaths(text: string): string;
32
43
  export declare function renderLocalGemmaFamiliarizePrompt(args: {
33
44
  userPrompt: string;
34
45
  summary: StructuralSummary;
35
46
  }): string;
47
+ export declare const MAX_BROWSE_CONTENT_CHARS = 12000;
48
+ export declare const MAX_MULTI_BROWSE_TOTAL_CONTENT_CHARS = 6000;
36
49
  /**
37
50
  * WEB-BROWSING (docs/WEB-BROWSING-DESIGN.md): build the advisory prompt for a
38
51
  * fetched web page. The model ANSWERS THE USER'S QUESTION grounded in the fetched
@@ -46,7 +59,7 @@ export declare function renderLocalGemmaFamiliarizePrompt(args: {
46
59
  * tolerates either prose or JSON. The title/content stay in the JSON DATA payload (escaped
47
60
  * — also defeats label-spoofing) and are NEVER interpolated into the instruction prose.
48
61
  *
49
- * Budget: cap title/url/userPrompt + content (lead), then SHRINK on ACTUAL rendered length
62
+ * Budget: cap title/url/userPrompt + content, then SHRINK on ACTUAL rendered length
50
63
  * (JSON.stringify can expand quote/backslash-heavy text) so the emitted JSON stays valid.
51
64
  */
52
65
  export declare function renderLocalGemmaBrowsePrompt(args: {
@@ -57,6 +70,52 @@ export declare function renderLocalGemmaBrowsePrompt(args: {
57
70
  };
58
71
  content: string;
59
72
  }): string;
73
+ export interface BrowseSourceInput {
74
+ url: string;
75
+ title: string;
76
+ content: string;
77
+ id?: number | string;
78
+ }
79
+ export declare const MAX_MULTI_BROWSE_RENDERED_PROMPT_CHARS = 8000;
80
+ export declare const MAX_MULTI_BROWSE_PER_SOURCE_URL_CHARS = 500;
81
+ export declare const MAX_MULTI_BROWSE_PER_SOURCE_TITLE_CHARS = 150;
82
+ /**
83
+ * Compute the per-source snippet extraction budget so that the resulting rendered
84
+ * prompt stays within MAX_MULTI_BROWSE_RENDERED_PROMPT_CHARS (8,000 chars) upfront.
85
+ *
86
+ * Framing overhead breakdown:
87
+ * - Fixed instructions / prose: ~1,140 chars
88
+ * - Top-level JSON scaffolding: ~40 chars
89
+ * - Per-source JSON scaffolding (keys, id, spacing): ~85 chars per source
90
+ * - User question: userPromptLength (capped to 1,000)
91
+ * - Source metadata: URLs (capped to perSourceUrlBudget) + titles (capped to perSourceTitleBudget)
92
+ * - JSON escaping safety margin: 200 chars
93
+ *
94
+ * Exported so route-browse.ts extracts snippets at the exact budget needed, ensuring
95
+ * the shrink loop does not need to cut content or discard query-relevant snippets (R2-F2 & R3-F3).
96
+ */
97
+ export declare function computeMultiBrowseContentBudget(params: {
98
+ survivingCount: number;
99
+ userPrompt?: string;
100
+ sourcesMetadata?: Array<{
101
+ url?: string;
102
+ title?: string;
103
+ }>;
104
+ }): number;
105
+ /**
106
+ * WEB-BROWSING (multi-source synthesis): build an advisory prompt for MULTIPLE
107
+ * fetched web sources (1 to 5). The local model answers the user's question,
108
+ * synthesizing facts across all sources, citing sources by number/title, and noting
109
+ * any discrepancies.
110
+ *
111
+ * Budget: Total rendered prompt budget strictly capped to MAX_MULTI_BROWSE_RENDERED_PROMPT_CHARS (8,000 chars, ~2,000 estimated input tokens)
112
+ * with combined source content bounded to MAX_MULTI_BROWSE_TOTAL_CONTENT_CHARS (6,000 chars, ~1,500 estimated tokens).
113
+ * Character budget bounds prompt size before dispatch; runtime tokenization and context capacity depend on the local model runner's configuration.
114
+ */
115
+ export declare function renderLocalGemmaMultiBrowsePrompt(args: {
116
+ userPrompt: string;
117
+ sources: BrowseSourceInput[];
118
+ }): string;
60
119
  export declare function boundedPriorBrainstormTurns(turns: string[] | undefined): string[];
61
120
  /**
62
121
  * WEB-BROWSING (search-route): turn the user's request + recent conversation into a
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-core",
3
- "version": "2.0.28",
3
+ "version": "2.0.30",
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.33",
3
+ "version": "2.0.35",
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.28",
51
+ "@quantiya/codevibe-core": "^2.0.30",
52
52
  "@quantiya/quorum-core": "^1.0.1",
53
53
  "dotenv": "^16.6.1",
54
54
  "express": "^5.1.0",
@@ -76,5 +76,14 @@
76
76
  "ts-jest": "^29.4.9",
77
77
  "ts-node": "^10.9.2",
78
78
  "typescript": "^5.9.3"
79
- }
79
+ },
80
+ "bundleDependencies": [
81
+ "@quantiya/codevibe-core",
82
+ "@quantiya/quorum-core",
83
+ "dotenv",
84
+ "express",
85
+ "graphql",
86
+ "uuid",
87
+ "ws"
88
+ ]
80
89
  }