context-mode 1.0.161 → 1.0.163
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.openclaw-plugin/openclaw.plugin.json +1 -1
- package/.openclaw-plugin/package.json +1 -1
- package/README.md +142 -28
- package/bin/statusline.mjs +24 -4
- package/build/adapters/antigravity/index.d.ts +1 -1
- package/build/adapters/antigravity-cli/index.d.ts +51 -0
- package/build/adapters/antigravity-cli/index.js +341 -0
- package/build/adapters/claude-code/hooks.d.ts +1 -0
- package/build/adapters/claude-code/hooks.js +3 -0
- package/build/adapters/claude-code/index.js +24 -5
- package/build/adapters/client-map.js +5 -0
- package/build/adapters/codex/hooks.d.ts +5 -1
- package/build/adapters/codex/hooks.js +5 -1
- package/build/adapters/codex/index.d.ts +9 -1
- package/build/adapters/codex/index.js +87 -5
- package/build/adapters/copilot-cli/hooks.d.ts +33 -0
- package/build/adapters/copilot-cli/hooks.js +64 -0
- package/build/adapters/copilot-cli/index.d.ts +48 -0
- package/build/adapters/copilot-cli/index.js +341 -0
- package/build/adapters/detect.d.ts +1 -1
- package/build/adapters/detect.js +71 -3
- package/build/adapters/openclaw/mcp-tools.js +1 -1
- package/build/adapters/opencode/index.js +31 -17
- package/build/adapters/opencode/zod3tov4.js +27 -6
- package/build/adapters/pi/extension.d.ts +2 -12
- package/build/adapters/pi/extension.js +114 -96
- package/build/adapters/types.d.ts +5 -4
- package/build/adapters/types.js +4 -3
- package/build/cache-heal.d.ts +48 -0
- package/build/cache-heal.js +150 -0
- package/build/cli.js +37 -97
- package/build/executor.d.ts +25 -0
- package/build/executor.js +143 -22
- package/build/opencode-plugin.js +5 -2
- package/build/routing-block.d.ts +8 -0
- package/build/routing-block.js +86 -0
- package/build/runtime.d.ts +0 -36
- package/build/runtime.js +107 -27
- package/build/search/flood-guard.d.ts +57 -0
- package/build/search/flood-guard.js +80 -0
- package/build/security.d.ts +8 -3
- package/build/security.js +155 -29
- package/build/server.d.ts +14 -0
- package/build/server.js +368 -350
- package/build/session/analytics.d.ts +8 -8
- package/build/session/analytics.js +18 -13
- package/build/session/db.d.ts +1 -0
- package/build/session/db.js +37 -4
- package/build/session/extract.d.ts +46 -0
- package/build/session/extract.js +764 -13
- package/build/session/project-attribution.js +14 -0
- package/build/store.d.ts +1 -1
- package/build/store.js +139 -25
- package/build/tool-naming.d.ts +4 -0
- package/build/tool-naming.js +24 -0
- package/build/util/jsonc.d.ts +14 -0
- package/build/util/jsonc.js +104 -0
- package/cli.bundle.mjs +260 -254
- package/configs/antigravity/GEMINI.md +2 -2
- package/configs/antigravity-cli/hooks/hooks.json +37 -0
- package/configs/antigravity-cli/hooks.json +37 -0
- package/configs/antigravity-cli/mcp_config.json +10 -0
- package/configs/antigravity-cli/plugin.json +14 -0
- package/configs/antigravity-cli/rules/context-mode.md +77 -0
- package/configs/antigravity-cli/skills/context-mode/SKILL.md +77 -0
- package/configs/claude-code/CLAUDE.md +2 -2
- package/configs/codex/AGENTS.md +2 -2
- package/configs/copilot-cli/.github/plugin/plugin.json +23 -0
- package/configs/copilot-cli/.mcp.json +12 -0
- package/configs/copilot-cli/README.md +47 -0
- package/configs/copilot-cli/hooks.json +41 -0
- package/configs/copilot-cli/skills/context-mode/SKILL.md +38 -0
- package/configs/gemini-cli/GEMINI.md +2 -2
- package/configs/jetbrains-copilot/copilot-instructions.md +2 -2
- package/configs/kilo/AGENTS.md +2 -2
- package/configs/kiro/KIRO.md +2 -2
- package/configs/omp/SYSTEM.md +2 -2
- package/configs/openclaw/AGENTS.md +2 -2
- package/configs/opencode/AGENTS.md +2 -2
- package/configs/qwen-code/QWEN.md +2 -2
- package/configs/vscode-copilot/copilot-instructions.md +2 -2
- package/configs/zed/AGENTS.md +2 -2
- package/hooks/antigravity-cli/payload.mjs +98 -0
- package/hooks/antigravity-cli/posttooluse.mjs +138 -0
- package/hooks/antigravity-cli/pretooluse.mjs +78 -0
- package/hooks/antigravity-cli/stop.mjs +58 -0
- package/hooks/codex/pretooluse.mjs +14 -4
- package/hooks/codex/stop.mjs +12 -4
- package/hooks/copilot-cli/posttooluse.mjs +79 -0
- package/hooks/copilot-cli/precompact.mjs +66 -0
- package/hooks/copilot-cli/pretooluse.mjs +41 -0
- package/hooks/copilot-cli/sessionstart.mjs +121 -0
- package/hooks/copilot-cli/stop.mjs +59 -0
- package/hooks/copilot-cli/userpromptsubmit.mjs +77 -0
- package/hooks/core/codex-caps.mjs +112 -0
- package/hooks/core/formatters.mjs +158 -7
- package/hooks/core/mcp-ready.mjs +37 -8
- package/hooks/core/routing.mjs +94 -8
- package/hooks/core/tool-naming.mjs +3 -0
- package/hooks/hooks.json +12 -1
- package/hooks/pretooluse.mjs +6 -2
- package/hooks/routing-block.mjs +2 -2
- package/hooks/security.bundle.mjs +2 -1
- package/hooks/session-db.bundle.mjs +11 -7
- package/hooks/session-directive.mjs +88 -20
- package/hooks/session-extract.bundle.mjs +2 -2
- package/hooks/session-helpers.mjs +21 -0
- package/hooks/session-loaders.mjs +8 -5
- package/hooks/sessionstart.mjs +53 -7
- package/hooks/stop.mjs +49 -0
- package/hooks/userpromptsubmit.mjs +9 -2
- package/openclaw.plugin.json +1 -1
- package/package.json +4 -10
- package/scripts/install-antigravity-cli-plugin.mjs +141 -0
- package/server.bundle.mjs +214 -205
- package/skills/ctx-insight/SKILL.md +12 -17
- package/build/util/db-lock.d.ts +0 -65
- package/build/util/db-lock.js +0 -166
- package/insight/index.html +0 -13
- package/insight/package.json +0 -55
- package/insight/server.mjs +0 -1265
- package/insight/src/components/analytics.tsx +0 -112
- package/insight/src/components/ui/badge.tsx +0 -52
- package/insight/src/components/ui/button.tsx +0 -58
- package/insight/src/components/ui/card.tsx +0 -103
- package/insight/src/components/ui/chart.tsx +0 -371
- package/insight/src/components/ui/collapsible.tsx +0 -19
- package/insight/src/components/ui/input.tsx +0 -20
- package/insight/src/components/ui/progress.tsx +0 -83
- package/insight/src/components/ui/scroll-area.tsx +0 -55
- package/insight/src/components/ui/separator.tsx +0 -23
- package/insight/src/components/ui/table.tsx +0 -114
- package/insight/src/components/ui/tabs.tsx +0 -82
- package/insight/src/components/ui/tooltip.tsx +0 -64
- package/insight/src/lib/api.ts +0 -144
- package/insight/src/lib/utils.ts +0 -6
- package/insight/src/main.tsx +0 -22
- package/insight/src/routeTree.gen.ts +0 -189
- package/insight/src/router.tsx +0 -19
- package/insight/src/routes/__root.tsx +0 -55
- package/insight/src/routes/enterprise.tsx +0 -316
- package/insight/src/routes/index.tsx +0 -1482
- package/insight/src/routes/knowledge.tsx +0 -221
- package/insight/src/routes/knowledge_.$dbHash.$sourceId.tsx +0 -137
- package/insight/src/routes/search.tsx +0 -97
- package/insight/src/routes/sessions.tsx +0 -179
- package/insight/src/routes/sessions_.$dbHash.$sessionId.tsx +0 -181
- package/insight/src/styles.css +0 -104
- package/insight/tsconfig.json +0 -29
- package/insight/vite.config.ts +0 -19
|
@@ -278,7 +278,7 @@ export interface AdapterDirEntry {
|
|
|
278
278
|
* so a single call surfaces "your work everywhere on this machine across
|
|
279
279
|
* all AI tools" (the marketing line).
|
|
280
280
|
*
|
|
281
|
-
* Returns ALL
|
|
281
|
+
* Returns ALL 17 adapters even when the dir doesn't exist on disk — the
|
|
282
282
|
* scanner functions filter to existing dirs. That keeps the enumeration
|
|
283
283
|
* pure / testable without filesystem dependencies.
|
|
284
284
|
*/
|
|
@@ -608,11 +608,11 @@ export declare function detectLocaleAndTz(): {
|
|
|
608
608
|
* the section disappears cleanly on a fresh install.
|
|
609
609
|
*
|
|
610
610
|
* Math constants:
|
|
611
|
-
* Opus 4
|
|
612
|
-
* Sonnet 4
|
|
613
|
-
* GPT-4o
|
|
614
|
-
* Gemini 2
|
|
615
|
-
* Haiku 4
|
|
611
|
+
* Opus 4.7/4.8 = $5.00 per 1M input tokens (fallback when PI_CONTEXT_MODE_PRICE_OUTPUT_PER_TOKEN not set)
|
|
612
|
+
* Sonnet 4.6 = $3.00 per 1M input tokens
|
|
613
|
+
* GPT-4o = $2.50 per 1M input tokens
|
|
614
|
+
* Gemini 2 = $1.25 per 1M input tokens
|
|
615
|
+
* Haiku 4.5 = $1.00 per 1M input tokens
|
|
616
616
|
* Cursor Pro = $20 / month → "X months of Cursor Pro"
|
|
617
617
|
* Claude Max = $200 / month → "X.X months of Claude Max"
|
|
618
618
|
* Weekend coding ≈ $73.67 → "X weekends of nonstop API coding"
|
|
@@ -669,8 +669,8 @@ export declare function renderHorizontalTimeline(days: TimelineDay[], locale: st
|
|
|
669
669
|
export declare function formatLocalDateTime(ms: number, locale: string, tz: string): string;
|
|
670
670
|
/**
|
|
671
671
|
* Per-token USD rate — resolves on every call.
|
|
672
|
-
* Dynamic when PI_CONTEXT_MODE_PRICE_OUTPUT_PER_TOKEN is set, Opus 4 input
|
|
673
|
-
* ($
|
|
672
|
+
* Dynamic when PI_CONTEXT_MODE_PRICE_OUTPUT_PER_TOKEN is set, Opus 4.7/4.8 input
|
|
673
|
+
* ($5 per 1M tokens) otherwise.
|
|
674
674
|
*/
|
|
675
675
|
export declare function pricePerToken(): number;
|
|
676
676
|
/**
|
|
@@ -359,7 +359,7 @@ export class AnalyticsEngine {
|
|
|
359
359
|
* so a single call surfaces "your work everywhere on this machine across
|
|
360
360
|
* all AI tools" (the marketing line).
|
|
361
361
|
*
|
|
362
|
-
* Returns ALL
|
|
362
|
+
* Returns ALL 17 adapters even when the dir doesn't exist on disk — the
|
|
363
363
|
* scanner functions filter to existing dirs. That keeps the enumeration
|
|
364
364
|
* pure / testable without filesystem dependencies.
|
|
365
365
|
*/
|
|
@@ -370,10 +370,12 @@ export function enumerateAdapterDirs(opts) {
|
|
|
370
370
|
["claude-code", [".claude"]],
|
|
371
371
|
["gemini-cli", [".gemini"]],
|
|
372
372
|
["antigravity", [".gemini"]],
|
|
373
|
+
["antigravity-cli", [".gemini"]],
|
|
373
374
|
["openclaw", [".openclaw"]],
|
|
374
375
|
["codex", [".codex"]],
|
|
375
376
|
["cursor", [".cursor"]],
|
|
376
377
|
["vscode-copilot", [".vscode"]],
|
|
378
|
+
["copilot-cli", [".copilot"]],
|
|
377
379
|
["kiro", [".kiro"]],
|
|
378
380
|
["pi", [".pi"]],
|
|
379
381
|
["omp", [".omp"]],
|
|
@@ -1188,10 +1190,12 @@ export const adapterLabels = {
|
|
|
1188
1190
|
"claude-code": "Claude Code",
|
|
1189
1191
|
"gemini-cli": "Gemini CLI",
|
|
1190
1192
|
"antigravity": "Antigravity",
|
|
1193
|
+
"antigravity-cli": "Antigravity CLI",
|
|
1191
1194
|
"openclaw": "Openclaw",
|
|
1192
1195
|
"codex": "Codex CLI",
|
|
1193
1196
|
"cursor": "Cursor",
|
|
1194
1197
|
"vscode-copilot": "VS Code Copilot",
|
|
1198
|
+
"copilot-cli": "GitHub Copilot CLI",
|
|
1195
1199
|
"kiro": "Kiro",
|
|
1196
1200
|
"pi": "Pi",
|
|
1197
1201
|
"omp": "OMP",
|
|
@@ -1393,11 +1397,11 @@ function shortPath(abs) {
|
|
|
1393
1397
|
* the section disappears cleanly on a fresh install.
|
|
1394
1398
|
*
|
|
1395
1399
|
* Math constants:
|
|
1396
|
-
* Opus 4
|
|
1397
|
-
* Sonnet 4
|
|
1398
|
-
* GPT-4o
|
|
1399
|
-
* Gemini 2
|
|
1400
|
-
* Haiku 4
|
|
1400
|
+
* Opus 4.7/4.8 = $5.00 per 1M input tokens (fallback when PI_CONTEXT_MODE_PRICE_OUTPUT_PER_TOKEN not set)
|
|
1401
|
+
* Sonnet 4.6 = $3.00 per 1M input tokens
|
|
1402
|
+
* GPT-4o = $2.50 per 1M input tokens
|
|
1403
|
+
* Gemini 2 = $1.25 per 1M input tokens
|
|
1404
|
+
* Haiku 4.5 = $1.00 per 1M input tokens
|
|
1401
1405
|
* Cursor Pro = $20 / month → "X months of Cursor Pro"
|
|
1402
1406
|
* Claude Max = $200 / month → "X.X months of Claude Max"
|
|
1403
1407
|
* Weekend coding ≈ $73.67 → "X weekends of nonstop API coding"
|
|
@@ -1428,7 +1432,7 @@ export function renderCostExample(lifetimeBytes, lifetimeTokens, lifetimeDays) {
|
|
|
1428
1432
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1429
1433
|
const _geminiUsd = ((lifetimeTokens * 1.25) / 1_000_000).toFixed(2);
|
|
1430
1434
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1431
|
-
const _haikuUsd = ((lifetimeTokens * 0
|
|
1435
|
+
const _haikuUsd = ((lifetimeTokens * 1.0) / 1_000_000).toFixed(2);
|
|
1432
1436
|
const usingDynamicPrice = process.env.PI_CONTEXT_MODE_PRICE_OUTPUT_PER_TOKEN !== undefined;
|
|
1433
1437
|
const modelId = process.env.PI_CONTEXT_MODE_MODEL_ID;
|
|
1434
1438
|
// Mert: "daha marketing ve business value e vermeli, math hesaplamalari ile
|
|
@@ -1442,7 +1446,7 @@ export function renderCostExample(lifetimeBytes, lifetimeTokens, lifetimeDays) {
|
|
|
1442
1446
|
out.push(` $${usdStr(lifetimeUsd)} of tokens your team didn't burn.`);
|
|
1443
1447
|
}
|
|
1444
1448
|
else {
|
|
1445
|
-
out.push(` $${usdStr(lifetimeUsd)} of Opus 4 tokens your team didn't burn.`);
|
|
1449
|
+
out.push(` $${usdStr(lifetimeUsd)} of Opus 4.7 tokens your team didn't burn.`);
|
|
1446
1450
|
}
|
|
1447
1451
|
out.push(` context-mode kept ${kb(lifetimeBytes)} out of context — that's ${cursorMonths} months of Cursor Pro paid for itself.`);
|
|
1448
1452
|
if (teamUsd > 0 && teamYearUsd > 0) {
|
|
@@ -1857,7 +1861,8 @@ function fmtNum(n) {
|
|
|
1857
1861
|
// ─────────────────────────────────────────────────────────
|
|
1858
1862
|
// ── Pricing (Bug #6) — per-token USD rate ─────────────────
|
|
1859
1863
|
// Reads PI_CONTEXT_MODE_PRICE_OUTPUT_PER_TOKEN when set by a Pi host;
|
|
1860
|
-
// falls back to the Opus 4 input rate ($
|
|
1864
|
+
// falls back to the Opus 4.7/4.8 input rate ($5/1M) for all other adapters.
|
|
1865
|
+
// Verified against platform.claude.com/docs/en/about-claude/pricing 2026-06.
|
|
1861
1866
|
//
|
|
1862
1867
|
// IMPORTANT: this is a FUNCTION, not a const. Pi sets the env var
|
|
1863
1868
|
// AFTER the MCP server has been imported (the bridge spawns the server
|
|
@@ -1869,8 +1874,8 @@ function fmtNum(n) {
|
|
|
1869
1874
|
// (Reverted module-load const semantics, PR #741 follow-up.)
|
|
1870
1875
|
/**
|
|
1871
1876
|
* Per-token USD rate — resolves on every call.
|
|
1872
|
-
* Dynamic when PI_CONTEXT_MODE_PRICE_OUTPUT_PER_TOKEN is set, Opus 4 input
|
|
1873
|
-
* ($
|
|
1877
|
+
* Dynamic when PI_CONTEXT_MODE_PRICE_OUTPUT_PER_TOKEN is set, Opus 4.7/4.8 input
|
|
1878
|
+
* ($5 per 1M tokens) otherwise.
|
|
1874
1879
|
*/
|
|
1875
1880
|
export function pricePerToken() {
|
|
1876
1881
|
const env = process.env.PI_CONTEXT_MODE_PRICE_OUTPUT_PER_TOKEN;
|
|
@@ -1879,7 +1884,7 @@ export function pricePerToken() {
|
|
|
1879
1884
|
if (Number.isFinite(parsed) && parsed > 0)
|
|
1880
1885
|
return parsed;
|
|
1881
1886
|
}
|
|
1882
|
-
return
|
|
1887
|
+
return 5 / 1_000_000; // Opus 4.7/4.8 input fallback
|
|
1883
1888
|
}
|
|
1884
1889
|
/**
|
|
1885
1890
|
* Back-compat alias for the original Opus-rate const (PR #401 architect
|
|
@@ -1890,7 +1895,7 @@ export function pricePerToken() {
|
|
|
1890
1895
|
*
|
|
1891
1896
|
* @deprecated Use pricePerToken() to honor PI_CONTEXT_MODE_PRICE_OUTPUT_PER_TOKEN.
|
|
1892
1897
|
*/
|
|
1893
|
-
export const OPUS_INPUT_PRICE_PER_TOKEN =
|
|
1898
|
+
export const OPUS_INPUT_PRICE_PER_TOKEN = 5 / 1_000_000;
|
|
1894
1899
|
/** Convert a token count to a USD string at the current per-token rate. */
|
|
1895
1900
|
export function tokensToUsd(tokens) {
|
|
1896
1901
|
const safe = Number.isFinite(tokens) && tokens > 0 ? tokens : 0;
|
package/build/session/db.d.ts
CHANGED
package/build/session/db.js
CHANGED
|
@@ -479,6 +479,7 @@ const S = {
|
|
|
479
479
|
getSessionStats: "getSessionStats",
|
|
480
480
|
getSessionRollup: "getSessionRollup",
|
|
481
481
|
getMaxFileEdits: "getMaxFileEdits",
|
|
482
|
+
getLatestCommitMessage: "getLatestCommitMessage",
|
|
482
483
|
incrementCompactCount: "incrementCompactCount",
|
|
483
484
|
upsertResume: "upsertResume",
|
|
484
485
|
getResume: "getResume",
|
|
@@ -731,7 +732,7 @@ export class SessionDB extends SQLiteBase {
|
|
|
731
732
|
COALESCE(SUM(CASE WHEN category = 'error' THEN 1 ELSE 0 END), 0) AS errors,
|
|
732
733
|
COUNT(DISTINCT type) AS unique_tools,
|
|
733
734
|
COUNT(DISTINCT CASE WHEN category = 'file' THEN data END) AS unique_files,
|
|
734
|
-
CASE WHEN SUM(CASE WHEN
|
|
735
|
+
CASE WHEN SUM(CASE WHEN type = 'git_commit' THEN 1 ELSE 0 END) > 0 THEN 1 ELSE 0 END AS has_commit,
|
|
735
736
|
CAST(COALESCE((MAX(strftime('%s', created_at)) - MIN(strftime('%s', created_at))) / 60.0, 0) AS INTEGER) AS duration_min,
|
|
736
737
|
COALESCE(SUM(CASE WHEN type = 'external_ref' THEN 1 ELSE 0 END), 0) AS sources_indexed,
|
|
737
738
|
CAST(COALESCE(SUM(bytes_avoided) / 1024.0, 0) AS INTEGER) AS total_chunks,
|
|
@@ -747,6 +748,16 @@ export class SessionDB extends SQLiteBase {
|
|
|
747
748
|
WHERE session_id = ? AND category = 'file' AND type IN ('file_edit', 'file_write')
|
|
748
749
|
GROUP BY data
|
|
749
750
|
)`);
|
|
751
|
+
// v1.0.161 (Bug 2): latest commit message from session's type='git_commit'
|
|
752
|
+
// events. Used by rollup spread to stamp commit_message symmetric with
|
|
753
|
+
// has_commit on every outgoing event. Separate prepared statement (vs.
|
|
754
|
+
// sub-select in getSessionRollup) keeps the binding shape uniform — every
|
|
755
|
+
// rollup query takes a single sessionId parameter.
|
|
756
|
+
p(S.getLatestCommitMessage, `SELECT data
|
|
757
|
+
FROM session_events
|
|
758
|
+
WHERE session_id = ? AND type = 'git_commit'
|
|
759
|
+
ORDER BY id DESC
|
|
760
|
+
LIMIT 1`);
|
|
750
761
|
p(S.incrementCompactCount, `UPDATE session_meta SET compact_count = compact_count + 1 WHERE session_id = ?`);
|
|
751
762
|
// ── Resume ──
|
|
752
763
|
p(S.upsertResume, `INSERT INTO session_resume (session_id, snapshot, event_count)
|
|
@@ -888,7 +899,12 @@ export class SessionDB extends SQLiteBase {
|
|
|
888
899
|
.slice(0, 16)
|
|
889
900
|
.toUpperCase();
|
|
890
901
|
const attribution = attributions?.[i];
|
|
891
|
-
|
|
902
|
+
// #827: store project_dir in canonical path shape so the search-time
|
|
903
|
+
// allow-set lookup (getSessionIdsForProject) matches regardless of the
|
|
904
|
+
// separator / trailing-slash form the host adapter happened to emit.
|
|
905
|
+
// normalizeWorktreePath is the same rule used for project-hash stability.
|
|
906
|
+
const rawProjectDir = String(attribution?.projectDir ?? event.project_dir ?? this._getSessionProjectDir(sessionId) ?? "").trim();
|
|
907
|
+
const projectDir = rawProjectDir === "" ? "" : normalizeWorktreePath(rawProjectDir);
|
|
892
908
|
const attributionSource = String(attribution?.source ?? event.attribution_source ?? "unknown");
|
|
893
909
|
const rawConfidence = Number(attribution?.confidence ?? event.attribution_confidence ?? 0);
|
|
894
910
|
const attributionConfidence = Number.isFinite(rawConfidence)
|
|
@@ -1020,11 +1036,26 @@ export class SessionDB extends SQLiteBase {
|
|
|
1020
1036
|
*/
|
|
1021
1037
|
getSessionIdsForProject(projectDir) {
|
|
1022
1038
|
try {
|
|
1039
|
+
// #827: match by canonical path shape, not raw bytes. The host adapter
|
|
1040
|
+
// may store `project_dir` in a different separator / trailing-slash
|
|
1041
|
+
// shape than the search path resolves the scope in — most visibly on
|
|
1042
|
+
// Windows, where attribution often carries `C:\Users\me\proj` while the
|
|
1043
|
+
// server resolves `C:/Users/me/proj`. An exact `project_dir = ?` match
|
|
1044
|
+
// then returned an EMPTY allow-set and ctx_search reported "No results
|
|
1045
|
+
// found" even though the content was present. We fold BOTH sides through
|
|
1046
|
+
// the same canonical rule used for project-hash stability
|
|
1047
|
+
// (normalizeWorktreePath): backslash → forward slash, then strip the
|
|
1048
|
+
// trailing slash. Normalizing in SQL (RTRIM(REPLACE(...))) covers rows
|
|
1049
|
+
// already written un-normalized without a migration, while the JS-side
|
|
1050
|
+
// normalize keeps the bound parameter in the identical shape. This
|
|
1051
|
+
// preserves the #737 project scope — distinct directories still differ
|
|
1052
|
+
// after normalization, so cross-project isolation is intact.
|
|
1053
|
+
const normalized = normalizeWorktreePath(projectDir);
|
|
1023
1054
|
const rows = this.db
|
|
1024
1055
|
.prepare(`SELECT DISTINCT session_id
|
|
1025
1056
|
FROM session_events
|
|
1026
|
-
WHERE project_dir = ?`)
|
|
1027
|
-
.all(
|
|
1057
|
+
WHERE RTRIM(REPLACE(project_dir, '\\', '/'), '/') = ?`)
|
|
1058
|
+
.all(normalized);
|
|
1028
1059
|
return rows.map((r) => r.session_id);
|
|
1029
1060
|
}
|
|
1030
1061
|
catch {
|
|
@@ -1063,6 +1094,7 @@ export class SessionDB extends SQLiteBase {
|
|
|
1063
1094
|
getSessionRollup(sessionId) {
|
|
1064
1095
|
const main = this.stmt(S.getSessionRollup).get(sessionId);
|
|
1065
1096
|
const maxRow = this.stmt(S.getMaxFileEdits).get(sessionId);
|
|
1097
|
+
const commitRow = this.stmt(S.getLatestCommitMessage).get(sessionId);
|
|
1066
1098
|
const meta = this.getSessionStats(sessionId);
|
|
1067
1099
|
// edit_test_cycles: heuristic — min(file edits, errors) approximates
|
|
1068
1100
|
// the number of edit-then-test attempts in a session. Exact pattern
|
|
@@ -1080,6 +1112,7 @@ export class SessionDB extends SQLiteBase {
|
|
|
1080
1112
|
unique_files: main?.unique_files ?? 0,
|
|
1081
1113
|
max_file_edits: maxRow?.max_file_edits ?? 0,
|
|
1082
1114
|
has_commit: main?.has_commit ?? 0,
|
|
1115
|
+
commit_message: commitRow?.data ?? "",
|
|
1083
1116
|
edit_test_cycles: editTestCycles,
|
|
1084
1117
|
duration_min: main?.duration_min ?? 0,
|
|
1085
1118
|
compact_count: meta?.compact_count ?? 0,
|
|
@@ -61,3 +61,49 @@ export declare function extractEvents(rawInput: HookInput): SessionEvent[];
|
|
|
61
61
|
* Returns an array of zero or more SessionEvents. Never throws.
|
|
62
62
|
*/
|
|
63
63
|
export declare function extractUserEvents(message: string): SessionEvent[];
|
|
64
|
+
/**
|
|
65
|
+
* Issue #4 (new PRD) — SessionStart settings + MCP servers snapshot.
|
|
66
|
+
*
|
|
67
|
+
* Emits ONE session_settings_snapshot event when ≥1 setting is available
|
|
68
|
+
* on the SessionStart input. The data field carries key:value tokens
|
|
69
|
+
* (mcp_count, mcp_servers, model, permission_mode) so the platform can
|
|
70
|
+
* compute MCP integration counts and primary-model adoption per org.
|
|
71
|
+
* mcp_servers list is truncated to first 8 names.
|
|
72
|
+
*/
|
|
73
|
+
export declare function extractSessionSettings(input: unknown): SessionEvent[];
|
|
74
|
+
/**
|
|
75
|
+
* §11 Layer 1 + Layer 3 — multilingual prompt features.
|
|
76
|
+
*
|
|
77
|
+
* Reference: context-mode-platform/docs/prds/2026-06-insight-data-flow/
|
|
78
|
+
* 11-multilingual-prompt-algorithm.md
|
|
79
|
+
*
|
|
80
|
+
* Script-agnostic via Unicode property regex (`\p{L}`, `\p{Lu}`,
|
|
81
|
+
* `\p{Script=X}`). No per-language tables, no franc/fasttext deps.
|
|
82
|
+
* Layer 1 returns 10 numeric/string features; Layer 3 appends a
|
|
83
|
+
* `prompt_word_tokens: string[]` array for the platform's streaming
|
|
84
|
+
* word-frequency UPSERT.
|
|
85
|
+
*
|
|
86
|
+
* Privacy: features carry no prose. Layer 3 tokens are deduped
|
|
87
|
+
* letter-only words ≥3 chars; platform aggregates by (org_id, week,
|
|
88
|
+
* word) so no individual token surfaces in UI.
|
|
89
|
+
*/
|
|
90
|
+
export interface PromptFeatures {
|
|
91
|
+
prompt_length: number;
|
|
92
|
+
prompt_word_count: number;
|
|
93
|
+
prompt_uppercase_ratio: number;
|
|
94
|
+
prompt_file_ref_count: number;
|
|
95
|
+
prompt_path_ref_count: number;
|
|
96
|
+
prompt_script_primary: string | null;
|
|
97
|
+
prompt_script_count: number;
|
|
98
|
+
prompt_question_glyph_count: number;
|
|
99
|
+
prompt_code_block_count: number;
|
|
100
|
+
prompt_url_count: number;
|
|
101
|
+
prompt_word_tokens: string[];
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Verbatim mirror of §11 Layer 1 reference implementation + Layer 3
|
|
105
|
+
* token extraction. Uses Unicode property regex per the spec — the
|
|
106
|
+
* "no regex" project default does NOT apply here because the spec
|
|
107
|
+
* explicitly mandates `\p{Script=X}` for script-agnostic classification.
|
|
108
|
+
*/
|
|
109
|
+
export declare function extractUserPromptFeatures(prompt: unknown): PromptFeatures;
|