@omercnet/paseo-context-mode 3.1.3 → 3.1.4-next.434.1
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/OVERVIEW.md +3 -3
- package/README.md +13 -15
- package/client/analytics-dashboard.tsx +745 -613
- package/client/controls.tsx +295 -0
- package/client/diagnostics-section.tsx +178 -0
- package/client/{context-mode-footer.tsx → footer.tsx} +22 -20
- package/client/knowledge-section.tsx +725 -697
- package/client/{context-mode-pill.tsx → pill.tsx} +5 -5
- package/client/scoped-knowledge-section.tsx +14 -20
- package/client/screen-scope.ts +12 -6
- package/client/settings-screen.tsx +94 -97
- package/client/surface.tsx +377 -0
- package/index.client.tsx +3 -3
- package/index.server.ts +18 -27
- package/npm-shrinkwrap.json +8 -1747
- package/package.json +7 -7
- package/server/actions.ts +91 -102
- package/server/analytics.ts +257 -308
- package/server/binary.ts +119 -94
- package/server/database.ts +463 -0
- package/server/handlers.ts +40 -95
- package/server/integration.ts +230 -361
- package/server/knowledge.ts +65 -137
- package/server/mcp-process.ts +135 -86
- package/server/storage-discovery.ts +46 -199
- package/shared/actions.ts +2 -27
- package/shared/analytics.ts +60 -33
- package/shared/contracts.ts +16 -47
- package/shared/knowledge.ts +62 -65
- package/shared/providers.ts +62 -0
- package/shared/settings.ts +33 -18
- package/client/actions-section.tsx +0 -621
- package/client/context-mode-surface.tsx +0 -444
- package/server/context-mode-db.ts +0 -481
- package/shared/index.ts +0 -5
|
@@ -1,239 +1,86 @@
|
|
|
1
1
|
import type { Dirent } from "node:fs";
|
|
2
|
-
import { lstat, readdir
|
|
3
|
-
import {
|
|
4
|
-
import { basename, isAbsolute, join, resolve } from "node:path";
|
|
2
|
+
import { lstat, readdir } from "node:fs/promises";
|
|
3
|
+
import { isAbsolute, join, resolve } from "node:path";
|
|
5
4
|
import type { AnalyticsWarning } from "../shared/analytics";
|
|
6
|
-
import { contextModeStorageRootFor, type ProviderOverrides, resolveProvider } from "./integration";
|
|
7
5
|
|
|
8
|
-
const
|
|
9
|
-
const
|
|
6
|
+
const MAX_PROJECTS = 256;
|
|
7
|
+
const MAX_DISCOVERY_WARNINGS = 10;
|
|
10
8
|
|
|
11
|
-
export interface
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
contentDir: string;
|
|
9
|
+
export interface ContextModeProjectDatabase {
|
|
10
|
+
/** Project key directory name, `sha256(projectPath).slice(0, 16)` upstream. */
|
|
11
|
+
project: string;
|
|
12
|
+
path: string;
|
|
16
13
|
}
|
|
17
14
|
|
|
18
15
|
export interface StorageDiscoveryResult {
|
|
19
|
-
|
|
16
|
+
databases: ContextModeProjectDatabase[];
|
|
20
17
|
warnings: AnalyticsWarning[];
|
|
21
18
|
}
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
env
|
|
26
|
-
|
|
27
|
-
/** Paseo `agents.providers`; each one contributes the storage its own env resolves to. */
|
|
28
|
-
providers?: ProviderOverrides;
|
|
20
|
+
/** Context Mode 2.x data dir: absolute `CONTEXT_MODE_DATA_DIR`, else `~/.context-mode`. */
|
|
21
|
+
export function resolveContextModeDataDir(env: NodeJS.ProcessEnv, home: string): string {
|
|
22
|
+
const configured = env.CONTEXT_MODE_DATA_DIR?.trim();
|
|
23
|
+
return configured && isAbsolute(configured) ? resolve(configured) : join(home, ".context-mode");
|
|
29
24
|
}
|
|
30
25
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function configuredDirectory(
|
|
37
|
-
value: string | undefined,
|
|
38
|
-
home: string,
|
|
39
|
-
envVar: string,
|
|
40
|
-
warnings: AnalyticsWarning[],
|
|
41
|
-
): string | null {
|
|
42
|
-
const trimmed = value?.trim();
|
|
43
|
-
if (!trimmed) return null;
|
|
44
|
-
if (trimmed === "~" || trimmed.startsWith("~/") || trimmed.startsWith("~\\")) {
|
|
45
|
-
return resolve(home, trimmed.slice(2));
|
|
46
|
-
}
|
|
47
|
-
if (isAbsolute(trimmed)) return resolve(trimmed);
|
|
48
|
-
warnings.push({
|
|
49
|
-
code: "invalid-storage-root",
|
|
50
|
-
message: `${envVar} was ignored because it is not an absolute path.`,
|
|
51
|
-
});
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function providerLocations(
|
|
56
|
-
home: string,
|
|
57
|
-
env: NodeJS.ProcessEnv,
|
|
58
|
-
warnings: AnalyticsWarning[],
|
|
59
|
-
platform: NodeJS.Platform,
|
|
60
|
-
providers: ProviderOverrides,
|
|
61
|
-
): ProviderLocation[] {
|
|
62
|
-
const configuredRoot = configuredDirectory(
|
|
63
|
-
env.CONTEXT_MODE_DIR,
|
|
64
|
-
home,
|
|
65
|
-
"CONTEXT_MODE_DIR",
|
|
66
|
-
warnings,
|
|
67
|
-
);
|
|
68
|
-
const configuredDataRoot = configuredDirectory(
|
|
69
|
-
env.CONTEXT_MODE_DATA_DIR,
|
|
70
|
-
home,
|
|
71
|
-
"CONTEXT_MODE_DATA_DIR",
|
|
72
|
-
warnings,
|
|
73
|
-
);
|
|
74
|
-
const claudeRoot =
|
|
75
|
-
configuredDirectory(env.CLAUDE_CONFIG_DIR, home, "CLAUDE_CONFIG_DIR", warnings) ??
|
|
76
|
-
join(home, ".claude");
|
|
77
|
-
const codexRoot =
|
|
78
|
-
configuredDirectory(env.CODEX_HOME, home, "CODEX_HOME", warnings) ?? join(home, ".codex");
|
|
79
|
-
const kimiRoot =
|
|
80
|
-
configuredDirectory(env.KIMI_CODE_HOME, home, "KIMI_CODE_HOME", warnings) ??
|
|
81
|
-
join(home, ".kimi-code");
|
|
82
|
-
const xdgRoot =
|
|
83
|
-
platform === "win32"
|
|
84
|
-
? (configuredDirectory(env.APPDATA, home, "APPDATA", warnings) ??
|
|
85
|
-
join(home, "AppData", "Roaming"))
|
|
86
|
-
: (configuredDirectory(env.XDG_CONFIG_HOME, home, "XDG_CONFIG_HOME", warnings) ??
|
|
87
|
-
join(home, ".config"));
|
|
88
|
-
|
|
89
|
-
const configured = Object.keys(providers).flatMap((id) => {
|
|
90
|
-
const { base, policy, env: providerEnv } = resolveProvider(id, providers);
|
|
91
|
-
const root = policy
|
|
92
|
-
? contextModeStorageRootFor(base, { home, env: { ...env, ...providerEnv } })
|
|
93
|
-
: null;
|
|
94
|
-
return root ? [{ provider: id, root }] : [];
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
return [
|
|
98
|
-
...(configuredRoot ? [{ provider: "custom", root: configuredRoot }] : []),
|
|
99
|
-
...(configuredDataRoot
|
|
100
|
-
? [{ provider: "custom-data", root: join(configuredDataRoot, "context-mode") }]
|
|
101
|
-
: []),
|
|
102
|
-
{ provider: "claude-code", root: join(claudeRoot, "context-mode") },
|
|
103
|
-
{ provider: "gemini-cli", root: join(home, ".gemini", "context-mode") },
|
|
104
|
-
{ provider: "openclaw", root: join(home, ".openclaw", "context-mode") },
|
|
105
|
-
{ provider: "codex", root: join(codexRoot, "context-mode") },
|
|
106
|
-
{ provider: "cursor", root: join(home, ".cursor", "context-mode") },
|
|
107
|
-
{ provider: "vscode-copilot", root: join(home, ".vscode", "context-mode") },
|
|
108
|
-
{ provider: "copilot-cli", root: join(home, ".copilot", "context-mode") },
|
|
109
|
-
{ provider: "kiro", root: join(home, ".kiro", "context-mode") },
|
|
110
|
-
{ provider: "pi", root: join(home, ".pi", "context-mode") },
|
|
111
|
-
{ provider: "omp", root: join(home, ".omp", "context-mode") },
|
|
112
|
-
{ provider: "qwen-code", root: join(home, ".qwen", "context-mode") },
|
|
113
|
-
{ provider: "kimi", root: join(kimiRoot, "context-mode") },
|
|
114
|
-
{ provider: "kilo", root: join(xdgRoot, "kilo", "context-mode") },
|
|
115
|
-
{ provider: "opencode", root: join(xdgRoot, "opencode", "context-mode") },
|
|
116
|
-
{ provider: "zed", root: join(home, ".config", "zed", "context-mode") },
|
|
117
|
-
{
|
|
118
|
-
provider: "jetbrains-copilot",
|
|
119
|
-
root: join(home, ".config", "JetBrains", "context-mode"),
|
|
120
|
-
},
|
|
121
|
-
...configured,
|
|
122
|
-
];
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function storageWarning(provider: string, message: string, database?: string): AnalyticsWarning {
|
|
126
|
-
return {
|
|
127
|
-
code: "storage-unavailable",
|
|
128
|
-
provider,
|
|
129
|
-
...(database ? { database } : {}),
|
|
130
|
-
message,
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
export async function discoverContextModeStorageRoots(
|
|
135
|
-
options: StorageDiscoveryOptions = {},
|
|
26
|
+
/** Lists `<dataDir>/projects/<key>/context.db`, skipping project directories without a database. */
|
|
27
|
+
export async function discoverContextModeDatabases(
|
|
28
|
+
dataDir: string,
|
|
136
29
|
): Promise<StorageDiscoveryResult> {
|
|
137
|
-
const
|
|
138
|
-
const env = options.env ?? process.env;
|
|
139
|
-
const warnings: AnalyticsWarning[] = [];
|
|
140
|
-
const roots: ProviderStorageRoot[] = [];
|
|
141
|
-
const seen = new Set<string>();
|
|
142
|
-
|
|
143
|
-
for (const location of providerLocations(
|
|
144
|
-
home,
|
|
145
|
-
env,
|
|
146
|
-
warnings,
|
|
147
|
-
options.platform ?? process.platform,
|
|
148
|
-
options.providers ?? {},
|
|
149
|
-
)) {
|
|
150
|
-
try {
|
|
151
|
-
const info = await lstat(location.root);
|
|
152
|
-
if (info.isSymbolicLink() || !info.isDirectory()) {
|
|
153
|
-
warnings.push(
|
|
154
|
-
storageWarning(
|
|
155
|
-
location.provider,
|
|
156
|
-
"The Context Mode storage root is not a regular directory.",
|
|
157
|
-
),
|
|
158
|
-
);
|
|
159
|
-
continue;
|
|
160
|
-
}
|
|
161
|
-
const canonical = await realpath(location.root);
|
|
162
|
-
if (seen.has(canonical)) continue;
|
|
163
|
-
seen.add(canonical);
|
|
164
|
-
roots.push({
|
|
165
|
-
provider: location.provider,
|
|
166
|
-
root: canonical,
|
|
167
|
-
sessionsDir: join(canonical, "sessions"),
|
|
168
|
-
contentDir: join(canonical, "content"),
|
|
169
|
-
});
|
|
170
|
-
} catch (error) {
|
|
171
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") continue;
|
|
172
|
-
warnings.push(
|
|
173
|
-
storageWarning(location.provider, "The Context Mode storage root could not be inspected."),
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
return { roots, warnings };
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export async function listRegularContextModeDatabases(
|
|
182
|
-
provider: string,
|
|
183
|
-
directory: string,
|
|
184
|
-
): Promise<{ files: string[]; warnings: AnalyticsWarning[] }> {
|
|
30
|
+
const projectsDir = join(dataDir, "projects");
|
|
185
31
|
let entries: Dirent[];
|
|
186
32
|
try {
|
|
187
|
-
entries = await readdir(
|
|
33
|
+
entries = await readdir(projectsDir, { withFileTypes: true });
|
|
188
34
|
} catch (error) {
|
|
189
|
-
if ((error as NodeJS.ErrnoException).code === "ENOENT") return {
|
|
35
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") return { databases: [], warnings: [] };
|
|
190
36
|
return {
|
|
191
|
-
|
|
37
|
+
databases: [],
|
|
192
38
|
warnings: [
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
39
|
+
{
|
|
40
|
+
code: "storage-unavailable",
|
|
41
|
+
message: "The Context Mode projects directory could not be read.",
|
|
42
|
+
},
|
|
197
43
|
],
|
|
198
44
|
};
|
|
199
45
|
}
|
|
200
46
|
|
|
201
|
-
const
|
|
202
|
-
.filter((entry) => entry.
|
|
203
|
-
.
|
|
204
|
-
|
|
47
|
+
const projects = entries
|
|
48
|
+
.filter((entry) => entry.isDirectory())
|
|
49
|
+
.map((entry) => entry.name)
|
|
50
|
+
.sort();
|
|
51
|
+
const databases: ContextModeProjectDatabase[] = [];
|
|
205
52
|
const warnings: AnalyticsWarning[] = [];
|
|
206
53
|
|
|
207
|
-
for (const
|
|
208
|
-
const path = join(
|
|
54
|
+
for (const project of projects.slice(0, MAX_PROJECTS)) {
|
|
55
|
+
const path = join(projectsDir, project, "context.db");
|
|
209
56
|
try {
|
|
210
57
|
const info = await lstat(path);
|
|
211
|
-
if (
|
|
212
|
-
|
|
213
|
-
} else if (warnings.length < MAX_LOCAL_DISCOVERY_WARNINGS) {
|
|
58
|
+
if (info.isFile()) databases.push({ project, path });
|
|
59
|
+
else if (warnings.length < MAX_DISCOVERY_WARNINGS) {
|
|
214
60
|
warnings.push({
|
|
215
61
|
code: "not-regular-database",
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
message: "Skipped a .db entry that is not a regular file.",
|
|
62
|
+
project,
|
|
63
|
+
message: "Skipped a context.db entry that is not a regular file.",
|
|
219
64
|
});
|
|
220
65
|
}
|
|
221
|
-
} catch {
|
|
222
|
-
if (
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
66
|
+
} catch (error) {
|
|
67
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT") continue;
|
|
68
|
+
if (warnings.length < MAX_DISCOVERY_WARNINGS) {
|
|
69
|
+
warnings.push({
|
|
70
|
+
code: "storage-unavailable",
|
|
71
|
+
project,
|
|
72
|
+
message: "The project database could not be inspected.",
|
|
73
|
+
});
|
|
226
74
|
}
|
|
227
75
|
}
|
|
228
76
|
}
|
|
229
77
|
|
|
230
|
-
if (
|
|
78
|
+
if (projects.length > MAX_PROJECTS) {
|
|
231
79
|
warnings.push({
|
|
232
80
|
code: "result-truncated",
|
|
233
|
-
|
|
234
|
-
message: `Only the first ${MAX_DATABASES_PER_DIRECTORY} database files in ${basename(directory)} were inspected.`,
|
|
81
|
+
message: `Only the first ${MAX_PROJECTS} of ${projects.length} Context Mode projects were inspected.`,
|
|
235
82
|
});
|
|
236
83
|
}
|
|
237
84
|
|
|
238
|
-
return {
|
|
85
|
+
return { databases, warnings };
|
|
239
86
|
}
|
package/shared/actions.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { defineRpc } from "@getpaseo/plugin";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
-
import { ContextModePlatformSchema, ContextModeProviderSchema } from "./
|
|
4
|
-
|
|
5
|
-
export const CONTEXT_MODE_TARGET_VERSION = "1.0.169" as const;
|
|
3
|
+
import { ContextModePlatformSchema, ContextModeProviderSchema } from "./providers";
|
|
6
4
|
|
|
7
5
|
const providerInput = z.object({ provider: ContextModeProviderSchema }).strict();
|
|
8
6
|
|
|
@@ -11,6 +9,7 @@ export const DoctorStatusRowSchema = z
|
|
|
11
9
|
status: z.enum(["ok", "warning", "error"]),
|
|
12
10
|
check: z.string().trim().min(1).max(256),
|
|
13
11
|
detail: z.string().max(4_096),
|
|
12
|
+
fix: z.string().max(4_096).optional(),
|
|
14
13
|
})
|
|
15
14
|
.strict();
|
|
16
15
|
|
|
@@ -22,36 +21,12 @@ export const DoctorReportSchema = z
|
|
|
22
21
|
})
|
|
23
22
|
.strict();
|
|
24
23
|
|
|
25
|
-
export const ContextModeActionSchema = z
|
|
26
|
-
.object({
|
|
27
|
-
program: z.string().trim().min(1).max(4_096),
|
|
28
|
-
args: z.array(z.string().max(4_096)).max(32),
|
|
29
|
-
currentVersion: z.string().trim().min(1).max(128).nullable(),
|
|
30
|
-
targetVersion: z.union([z.literal(CONTEXT_MODE_TARGET_VERSION), z.literal("latest")]),
|
|
31
|
-
platform: ContextModePlatformSchema,
|
|
32
|
-
requiresRestart: z.boolean(),
|
|
33
|
-
})
|
|
34
|
-
.strict();
|
|
35
|
-
|
|
36
24
|
export const getContextModeDoctorReport = defineRpc({
|
|
37
25
|
name: "context-mode.actions.doctor",
|
|
38
26
|
input: providerInput,
|
|
39
27
|
output: DoctorReportSchema,
|
|
40
28
|
});
|
|
41
29
|
|
|
42
|
-
export const getContextModeInstallAction = defineRpc({
|
|
43
|
-
name: "context-mode.actions.install",
|
|
44
|
-
input: providerInput,
|
|
45
|
-
output: ContextModeActionSchema,
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
export const getContextModeUpgradeAction = defineRpc({
|
|
49
|
-
name: "context-mode.actions.upgrade",
|
|
50
|
-
input: providerInput,
|
|
51
|
-
output: ContextModeActionSchema,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
30
|
export type DoctorStatusRow = z.infer<typeof DoctorStatusRowSchema>;
|
|
55
31
|
export type DoctorReport = z.infer<typeof DoctorReportSchema>;
|
|
56
|
-
export type ContextModeAction = z.infer<typeof ContextModeActionSchema>;
|
|
57
32
|
export type ContextModeActionInput = z.infer<typeof providerInput>;
|
package/shared/analytics.ts
CHANGED
|
@@ -1,27 +1,32 @@
|
|
|
1
1
|
import { defineRpc } from "@getpaseo/plugin";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
|
|
4
|
-
export const CONTEXT_MODE_ANALYTICS_SCHEMA_VERSION =
|
|
5
|
-
export const
|
|
4
|
+
export const CONTEXT_MODE_ANALYTICS_SCHEMA_VERSION = 2 as const;
|
|
5
|
+
export const SUPPORTED_CONTEXT_MODE_DATABASE_USER_VERSION = 6 as const;
|
|
6
6
|
|
|
7
7
|
const nonNegativeInteger = z.number().int().nonnegative();
|
|
8
8
|
const nonNegativeNumber = z.number().finite().nonnegative();
|
|
9
|
+
const timestamp = z.string().datetime().nullable();
|
|
9
10
|
|
|
11
|
+
/** Byte totals of Context Mode tool calls: produced in the sandbox, returned to the agent, kept out. */
|
|
10
12
|
export const AnalyticsByteAccountingSchema = z
|
|
11
13
|
.object({
|
|
12
|
-
|
|
13
|
-
avoidedBytes: nonNegativeInteger,
|
|
14
|
+
producedBytes: nonNegativeInteger,
|
|
14
15
|
returnedBytes: nonNegativeInteger,
|
|
15
|
-
snapshotBytes: nonNegativeInteger,
|
|
16
|
-
indexedBytes: nonNegativeInteger,
|
|
17
16
|
savedBytes: nonNegativeInteger,
|
|
17
|
+
indexedBytes: nonNegativeInteger,
|
|
18
18
|
})
|
|
19
19
|
.strict();
|
|
20
20
|
|
|
21
|
+
const savingsFields = {
|
|
22
|
+
savedTokens: nonNegativeInteger,
|
|
23
|
+
savingsPercent: nonNegativeNumber.max(100),
|
|
24
|
+
byteAccounting: AnalyticsByteAccountingSchema,
|
|
25
|
+
};
|
|
26
|
+
|
|
21
27
|
export const AnalyticsTotalsSchema = z
|
|
22
28
|
.object({
|
|
23
|
-
|
|
24
|
-
databases: nonNegativeInteger,
|
|
29
|
+
agents: nonNegativeInteger,
|
|
25
30
|
projects: nonNegativeInteger,
|
|
26
31
|
sessions: nonNegativeInteger,
|
|
27
32
|
events: nonNegativeInteger,
|
|
@@ -30,27 +35,47 @@ export const AnalyticsTotalsSchema = z
|
|
|
30
35
|
indexedChunks: nonNegativeInteger,
|
|
31
36
|
inputTokens: nonNegativeInteger,
|
|
32
37
|
outputTokens: nonNegativeInteger,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
byteAccounting: AnalyticsByteAccountingSchema,
|
|
38
|
+
...savingsFields,
|
|
39
|
+
lastActivityAt: timestamp,
|
|
36
40
|
})
|
|
37
41
|
.strict();
|
|
38
42
|
|
|
39
|
-
|
|
43
|
+
/** One row per Context Mode `--agent` id recorded in the databases (claude-code, codex, ...). */
|
|
44
|
+
export const AgentAnalyticsSchema = z
|
|
40
45
|
.object({
|
|
41
|
-
|
|
42
|
-
databases: nonNegativeInteger,
|
|
46
|
+
agent: z.string().min(1).max(128),
|
|
43
47
|
projects: nonNegativeInteger,
|
|
44
48
|
sessions: nonNegativeInteger,
|
|
45
|
-
events: nonNegativeInteger,
|
|
46
49
|
toolCalls: nonNegativeInteger,
|
|
47
50
|
indexedSources: nonNegativeInteger,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
...savingsFields,
|
|
52
|
+
})
|
|
53
|
+
.strict();
|
|
54
|
+
|
|
55
|
+
export const ProjectAnalyticsSchema = z
|
|
56
|
+
.object({
|
|
57
|
+
path: z.string().min(1).max(4_096),
|
|
58
|
+
worktrees: nonNegativeInteger,
|
|
59
|
+
sessions: nonNegativeInteger,
|
|
60
|
+
toolCalls: nonNegativeInteger,
|
|
61
|
+
indexedSources: nonNegativeInteger,
|
|
62
|
+
...savingsFields,
|
|
63
|
+
lastActivityAt: timestamp,
|
|
64
|
+
})
|
|
65
|
+
.strict();
|
|
66
|
+
|
|
67
|
+
/** Paseo provider whose Context Mode store holds the row, for Resume and Forget; null when none reaches it. */
|
|
68
|
+
const storeProvider = z.string().min(1).max(128).nullable();
|
|
69
|
+
|
|
70
|
+
/** One recorded agent session, newest first; the plugin's own `paseo-context-mode` calls are excluded. */
|
|
71
|
+
export const SessionAnalyticsSchema = z
|
|
72
|
+
.object({
|
|
73
|
+
sessionId: z.string().min(1).max(256),
|
|
74
|
+
agent: z.string().min(1).max(128),
|
|
75
|
+
projectPath: z.string().min(1).max(4_096),
|
|
76
|
+
events: nonNegativeInteger,
|
|
77
|
+
lastActivityAt: timestamp,
|
|
78
|
+
provider: storeProvider,
|
|
54
79
|
})
|
|
55
80
|
.strict();
|
|
56
81
|
|
|
@@ -72,32 +97,30 @@ export const DailyAnalyticsSchema = z
|
|
|
72
97
|
|
|
73
98
|
export const IndexedSourceAnalyticsSchema = z
|
|
74
99
|
.object({
|
|
75
|
-
|
|
100
|
+
agent: z.string().min(1).max(128),
|
|
101
|
+
projectPath: z.string().min(1).max(4_096),
|
|
76
102
|
source: z.string().min(1).max(4_096),
|
|
103
|
+
kind: z.enum(["path", "content", "url"]),
|
|
77
104
|
chunks: nonNegativeInteger,
|
|
78
|
-
codeChunks: nonNegativeInteger,
|
|
79
105
|
indexedBytes: nonNegativeInteger,
|
|
80
|
-
indexedAt:
|
|
81
|
-
|
|
82
|
-
detail: z.string().max(512).optional(),
|
|
106
|
+
indexedAt: timestamp,
|
|
107
|
+
provider: storeProvider,
|
|
83
108
|
})
|
|
84
109
|
.strict();
|
|
85
110
|
|
|
86
111
|
export const AnalyticsWarningSchema = z
|
|
87
112
|
.object({
|
|
88
113
|
code: z.enum([
|
|
89
|
-
"invalid-storage-root",
|
|
90
114
|
"storage-unavailable",
|
|
91
115
|
"not-regular-database",
|
|
92
116
|
"database-open-failed",
|
|
117
|
+
"database-locked",
|
|
93
118
|
"unsupported-schema",
|
|
94
119
|
"database-query-failed",
|
|
95
|
-
"inconsistent-index",
|
|
96
120
|
"result-truncated",
|
|
97
121
|
"warning-limit",
|
|
98
122
|
]),
|
|
99
|
-
|
|
100
|
-
database: z.string().min(1).max(512).optional(),
|
|
123
|
+
project: z.string().min(1).max(128).optional(),
|
|
101
124
|
message: z.string().min(1).max(512),
|
|
102
125
|
})
|
|
103
126
|
.strict();
|
|
@@ -105,11 +128,13 @@ export const AnalyticsWarningSchema = z
|
|
|
105
128
|
export const ContextModeAnalyticsDashboardSchema = z
|
|
106
129
|
.object({
|
|
107
130
|
schemaVersion: z.literal(CONTEXT_MODE_ANALYTICS_SCHEMA_VERSION),
|
|
108
|
-
contextModeVersion: z.
|
|
131
|
+
contextModeVersion: z.string().min(1).max(64).nullable(),
|
|
109
132
|
completeness: z.enum(["complete", "partial", "unsupported"]),
|
|
110
133
|
warnings: z.array(AnalyticsWarningSchema).max(20),
|
|
111
134
|
totals: AnalyticsTotalsSchema,
|
|
112
|
-
|
|
135
|
+
byAgent: z.array(AgentAnalyticsSchema).max(32),
|
|
136
|
+
byProject: z.array(ProjectAnalyticsSchema).max(50),
|
|
137
|
+
recentSessions: z.array(SessionAnalyticsSchema).max(20),
|
|
113
138
|
byCategory: z.array(CategoryAnalyticsSchema).max(128),
|
|
114
139
|
byDay: z.array(DailyAnalyticsSchema).max(400),
|
|
115
140
|
sources: z.array(IndexedSourceAnalyticsSchema).max(2_000),
|
|
@@ -125,7 +150,9 @@ export const getContextModeAnalyticsDashboard = defineRpc({
|
|
|
125
150
|
|
|
126
151
|
export type AnalyticsByteAccounting = z.infer<typeof AnalyticsByteAccountingSchema>;
|
|
127
152
|
export type AnalyticsTotals = z.infer<typeof AnalyticsTotalsSchema>;
|
|
128
|
-
export type
|
|
153
|
+
export type AgentAnalytics = z.infer<typeof AgentAnalyticsSchema>;
|
|
154
|
+
export type ProjectAnalytics = z.infer<typeof ProjectAnalyticsSchema>;
|
|
155
|
+
export type SessionAnalytics = z.infer<typeof SessionAnalyticsSchema>;
|
|
129
156
|
export type CategoryAnalytics = z.infer<typeof CategoryAnalyticsSchema>;
|
|
130
157
|
export type DailyAnalytics = z.infer<typeof DailyAnalyticsSchema>;
|
|
131
158
|
export type IndexedSourceAnalytics = z.infer<typeof IndexedSourceAnalyticsSchema>;
|
package/shared/contracts.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { defineRpc } from "@getpaseo/plugin";
|
|
2
2
|
import { z } from "zod";
|
|
3
|
+
import { ContextModePlatformSchema } from "./providers";
|
|
3
4
|
|
|
4
5
|
const refreshInput = z.object({ fresh: z.boolean().default(false) }).strict();
|
|
5
|
-
|
|
6
|
+
/** `settings`: the user's own binary; `bundled`: the runtime shipped with the plugin. */
|
|
7
|
+
const binarySource = z.enum(["settings", "bundled"]);
|
|
6
8
|
const failureCode = z.enum([
|
|
7
9
|
"not-installed",
|
|
8
10
|
"invalid-settings",
|
|
@@ -20,8 +22,6 @@ export const BinaryStatusSchema = z.discriminatedUnion("state", [
|
|
|
20
22
|
binaryPath: z.string(),
|
|
21
23
|
source: binarySource,
|
|
22
24
|
version: z.string().nullable(),
|
|
23
|
-
supportsDoctor: z.boolean(),
|
|
24
|
-
supportsStats: z.boolean(),
|
|
25
25
|
checkedAt: z.string().datetime(),
|
|
26
26
|
}),
|
|
27
27
|
z.object({
|
|
@@ -32,37 +32,19 @@ export const BinaryStatusSchema = z.discriminatedUnion("state", [
|
|
|
32
32
|
}),
|
|
33
33
|
]);
|
|
34
34
|
|
|
35
|
-
export const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
code: failureCode,
|
|
45
|
-
message: z.string().max(4_096),
|
|
46
|
-
checkedAt: z.string().datetime(),
|
|
47
|
-
}),
|
|
48
|
-
]);
|
|
49
|
-
|
|
50
|
-
export const ProviderIntegrationSchema = z.object({
|
|
51
|
-
provider: z.string(),
|
|
52
|
-
platform: z.string(),
|
|
53
|
-
activation: z.enum(["native", "mcp", "disabled"]),
|
|
54
|
-
storageRoot: z.string(),
|
|
55
|
-
reusesExistingStorage: z.boolean(),
|
|
56
|
-
detail: z.string().max(4_096),
|
|
57
|
-
});
|
|
35
|
+
export const ProviderIntegrationSchema = z
|
|
36
|
+
.object({
|
|
37
|
+
provider: z.string(),
|
|
38
|
+
/** `--agent` id, or null when Context Mode 2.x cannot serve this provider over MCP. */
|
|
39
|
+
platform: ContextModePlatformSchema.nullable(),
|
|
40
|
+
activation: z.enum(["native", "mcp", "disabled"]),
|
|
41
|
+
detail: z.string().max(4_096),
|
|
42
|
+
})
|
|
43
|
+
.strict();
|
|
58
44
|
|
|
59
|
-
export const IntegrationAuditSchema = z
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
injectionEnabled: z.boolean(),
|
|
63
|
-
providers: z.array(ProviderIntegrationSchema),
|
|
64
|
-
checkedAt: z.string().datetime(),
|
|
65
|
-
});
|
|
45
|
+
export const IntegrationAuditSchema = z
|
|
46
|
+
.object({ providers: z.array(ProviderIntegrationSchema) })
|
|
47
|
+
.strict();
|
|
66
48
|
|
|
67
49
|
export const getContextModeStatus = defineRpc({
|
|
68
50
|
name: "context-mode.status",
|
|
@@ -70,26 +52,13 @@ export const getContextModeStatus = defineRpc({
|
|
|
70
52
|
output: BinaryStatusSchema,
|
|
71
53
|
});
|
|
72
54
|
|
|
73
|
-
export const getContextModeDoctor = defineRpc({
|
|
74
|
-
name: "context-mode.doctor",
|
|
75
|
-
input: refreshInput,
|
|
76
|
-
output: CommandReportSchema,
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
export const getContextModeStats = defineRpc({
|
|
80
|
-
name: "context-mode.stats",
|
|
81
|
-
input: refreshInput,
|
|
82
|
-
output: CommandReportSchema,
|
|
83
|
-
});
|
|
84
|
-
|
|
85
55
|
export const getContextModeIntegrationAudit = defineRpc({
|
|
86
56
|
name: "context-mode.integration-audit",
|
|
87
|
-
input:
|
|
57
|
+
input: z.object({}).strict(),
|
|
88
58
|
output: IntegrationAuditSchema,
|
|
89
59
|
});
|
|
90
60
|
|
|
91
61
|
export type BinaryStatus = z.infer<typeof BinaryStatusSchema>;
|
|
92
|
-
export type CommandReport = z.infer<typeof CommandReportSchema>;
|
|
93
62
|
export type IntegrationAudit = z.infer<typeof IntegrationAuditSchema>;
|
|
94
63
|
export type ProviderIntegration = z.infer<typeof ProviderIntegrationSchema>;
|
|
95
64
|
export type ContextModeRefreshInput = z.infer<typeof refreshInput>;
|