@phnx-labs/agents-cli 1.21.2 → 1.21.3
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/CHANGELOG.md +34 -0
- package/dist/bin/agents +0 -0
- package/dist/commands/computer-actions.d.ts +4 -0
- package/dist/commands/computer-actions.js +34 -0
- package/dist/commands/computer.js +4 -2
- package/dist/commands/perf.d.ts +16 -0
- package/dist/commands/perf.js +11 -1
- package/dist/commands/projects.d.ts +11 -1
- package/dist/commands/projects.js +16 -2
- package/dist/commands/sessions-picker.js +17 -2
- package/dist/commands/sessions.d.ts +5 -0
- package/dist/commands/sessions.js +14 -0
- package/dist/index.js +8 -0
- package/dist/lib/browser/service.js +13 -0
- package/dist/lib/computer/dispatch.d.ts +3 -1
- package/dist/lib/computer/dispatch.js +10 -2
- package/dist/lib/event-stream.d.ts +2 -0
- package/dist/lib/event-stream.js +3 -0
- package/dist/lib/events.d.ts +3 -1
- package/dist/lib/events.js +4 -2
- package/dist/lib/git.d.ts +14 -0
- package/dist/lib/git.js +36 -0
- package/dist/lib/hooks/profile.js +1 -14
- package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/percentile.d.ts +12 -0
- package/dist/lib/percentile.js +24 -0
- package/dist/lib/perf/db.d.ts +1 -2
- package/dist/lib/perf/db.js +2 -14
- package/dist/lib/plugins.js +12 -1
- package/dist/lib/resources.d.ts +16 -0
- package/dist/lib/resources.js +25 -14
- package/dist/lib/routines.js +1 -14
- package/dist/lib/runner.js +8 -1
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/session/db.d.ts +16 -1
- package/dist/lib/session/db.js +227 -4
- package/dist/lib/session/discover.d.ts +28 -0
- package/dist/lib/session/discover.js +42 -1
- package/dist/lib/session/highlights.d.ts +24 -4
- package/dist/lib/session/highlights.js +52 -7
- package/dist/lib/session/parse.js +19 -3
- package/dist/lib/session/prompt.d.ts +19 -0
- package/dist/lib/session/prompt.js +43 -0
- package/dist/lib/session/types.d.ts +42 -0
- package/dist/lib/types.d.ts +14 -0
- package/package.json +1 -1
package/dist/lib/git.js
CHANGED
|
@@ -371,6 +371,42 @@ export function readRepoState(repoPath) {
|
|
|
371
371
|
const dirty = porcelain != null && porcelain.length > 0;
|
|
372
372
|
return { branch, head, dirty };
|
|
373
373
|
}
|
|
374
|
+
/** Memoized per repoRoot — a resolveResource()/listResources()/plugin-discovery
|
|
375
|
+
* call that touches many resources from the SAME DotAgents repo must not shell
|
|
376
|
+
* out to git once per resource. */
|
|
377
|
+
const _snapshotShaCache = new Map();
|
|
378
|
+
/**
|
|
379
|
+
* The short HEAD sha of the git repo at `repoRoot` (`git -C <repoRoot>
|
|
380
|
+
* rev-parse --short HEAD`), for provenance — "which commit of this DotAgents
|
|
381
|
+
* repo was this resource/plugin resolved from". `undefined` when `repoRoot`
|
|
382
|
+
* isn't a git repo (or has no commits yet), never a throw.
|
|
383
|
+
*
|
|
384
|
+
* Deliberately synchronous + resolved once and cached: callers (resources.ts,
|
|
385
|
+
* plugins.ts) attach this as a lazy getter on the resolved object, so a
|
|
386
|
+
* consumer that never inspects provenance never pays for the git shell-out —
|
|
387
|
+
* see {@link ResolvedResource.snapshotSha} / {@link DiscoveredPlugin.snapshotSha}.
|
|
388
|
+
*/
|
|
389
|
+
export function resolveSnapshotSha(repoRoot) {
|
|
390
|
+
const cached = _snapshotShaCache.get(repoRoot);
|
|
391
|
+
if (cached !== undefined || _snapshotShaCache.has(repoRoot))
|
|
392
|
+
return cached;
|
|
393
|
+
let sha;
|
|
394
|
+
try {
|
|
395
|
+
const raw = execFileSync('git', ['-C', repoRoot, 'rev-parse', '--short', 'HEAD'], {
|
|
396
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
397
|
+
}).toString().trim();
|
|
398
|
+
sha = raw || undefined;
|
|
399
|
+
}
|
|
400
|
+
catch {
|
|
401
|
+
sha = undefined;
|
|
402
|
+
}
|
|
403
|
+
_snapshotShaCache.set(repoRoot, sha);
|
|
404
|
+
return sha;
|
|
405
|
+
}
|
|
406
|
+
/** Test seam: clear the memoized snapshot-sha cache between test cases. */
|
|
407
|
+
export function _resetSnapshotShaCacheForTest() {
|
|
408
|
+
_snapshotShaCache.clear();
|
|
409
|
+
}
|
|
374
410
|
/**
|
|
375
411
|
* Get the current GitHub username using gh CLI.
|
|
376
412
|
* Returns null if gh is not installed or user is not authenticated.
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
import * as fs from 'fs';
|
|
13
13
|
import * as path from 'path';
|
|
14
14
|
import { getLogsDir } from '../state.js';
|
|
15
|
+
import { percentile } from '../percentile.js';
|
|
15
16
|
/**
|
|
16
17
|
* Load every `hook.fire` event from the last `days` daily log files.
|
|
17
18
|
* Lines that aren't JSON or aren't `hook.fire` events are silently skipped —
|
|
@@ -53,20 +54,6 @@ export function loadHookFireEvents(days = 7, logsDir = getLogsDir()) {
|
|
|
53
54
|
}
|
|
54
55
|
return events;
|
|
55
56
|
}
|
|
56
|
-
/** Percentile of a sorted-ascending array. p in [0,100]. Linear interpolation. */
|
|
57
|
-
function percentile(sorted, p) {
|
|
58
|
-
if (sorted.length === 0)
|
|
59
|
-
return 0;
|
|
60
|
-
if (sorted.length === 1)
|
|
61
|
-
return sorted[0];
|
|
62
|
-
const rank = (p / 100) * (sorted.length - 1);
|
|
63
|
-
const lo = Math.floor(rank);
|
|
64
|
-
const hi = Math.ceil(rank);
|
|
65
|
-
if (lo === hi)
|
|
66
|
-
return sorted[lo];
|
|
67
|
-
const frac = rank - lo;
|
|
68
|
-
return sorted[lo] * (1 - frac) + sorted[hi] * frac;
|
|
69
|
-
}
|
|
70
57
|
/** Aggregate fire events into a per-hook profile, sorted by p99 desc. */
|
|
71
58
|
export function aggregateHookProfile(events) {
|
|
72
59
|
const byHook = new Map();
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Percentile of a sorted-ascending array, linear interpolation. p in [0,100].
|
|
3
|
+
*
|
|
4
|
+
* Deliberately its own file with zero imports: `perf/db.ts` (the SQLite
|
|
5
|
+
* warehouse), `hooks/profile.ts` (the legacy JSONL hook profile), and
|
|
6
|
+
* `routines.ts` (routineStats) all need this exact formula, but `routines.ts`
|
|
7
|
+
* and `hooks/profile.ts` must NOT pull in `perf/db.ts`'s `../sqlite.js`
|
|
8
|
+
* dependency just to round a percentile — sqlite is a heavier, perf-warehouse-
|
|
9
|
+
* specific dependency that has no business loading into every routines- or
|
|
10
|
+
* hooks-touching code path.
|
|
11
|
+
*/
|
|
12
|
+
export declare function percentile(sorted: number[], p: number): number;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Percentile of a sorted-ascending array, linear interpolation. p in [0,100].
|
|
3
|
+
*
|
|
4
|
+
* Deliberately its own file with zero imports: `perf/db.ts` (the SQLite
|
|
5
|
+
* warehouse), `hooks/profile.ts` (the legacy JSONL hook profile), and
|
|
6
|
+
* `routines.ts` (routineStats) all need this exact formula, but `routines.ts`
|
|
7
|
+
* and `hooks/profile.ts` must NOT pull in `perf/db.ts`'s `../sqlite.js`
|
|
8
|
+
* dependency just to round a percentile — sqlite is a heavier, perf-warehouse-
|
|
9
|
+
* specific dependency that has no business loading into every routines- or
|
|
10
|
+
* hooks-touching code path.
|
|
11
|
+
*/
|
|
12
|
+
export function percentile(sorted, p) {
|
|
13
|
+
if (sorted.length === 0)
|
|
14
|
+
return 0;
|
|
15
|
+
if (sorted.length === 1)
|
|
16
|
+
return sorted[0];
|
|
17
|
+
const rank = (p / 100) * (sorted.length - 1);
|
|
18
|
+
const lo = Math.floor(rank);
|
|
19
|
+
const hi = Math.ceil(rank);
|
|
20
|
+
if (lo === hi)
|
|
21
|
+
return sorted[lo];
|
|
22
|
+
const frac = rank - lo;
|
|
23
|
+
return sorted[lo] * (1 - frac) + sorted[hi] * frac;
|
|
24
|
+
}
|
package/dist/lib/perf/db.d.ts
CHANGED
|
@@ -8,14 +8,13 @@ import Database from '../sqlite.js';
|
|
|
8
8
|
import type { AggregateOptions, PerfAggregateRow } from './types.js';
|
|
9
9
|
export type { AggregateOptions, PerfAggregateRow, PerfSample } from './types.js';
|
|
10
10
|
export { recordSample, shortSessionId, resolveSpoolPath } from './spool.js';
|
|
11
|
+
export { percentile } from '../percentile.js';
|
|
11
12
|
export declare const PERF_SCHEMA_VERSION = 1;
|
|
12
13
|
export declare const DEFAULT_RETENTION_DAYS = 30;
|
|
13
14
|
/** Test seam — redirect the warehouse path (like AGENTS_EVENTS_PATH). */
|
|
14
15
|
export declare function _resetPerfDbForTest(overridePath?: string | null): void;
|
|
15
16
|
/** Drain the NDJSON spool into samples. Idempotent; truncates on success. */
|
|
16
17
|
export declare function drainSpool(db?: Database.Database): number;
|
|
17
|
-
/** Percentile of a sorted-ascending array. p in [0,100]. */
|
|
18
|
-
export declare function percentile(sorted: number[], p: number): number;
|
|
19
18
|
/**
|
|
20
19
|
* Aggregate samples by (kind, label) with p50/p95/p99. Drains the spool first.
|
|
21
20
|
*
|
package/dist/lib/perf/db.js
CHANGED
|
@@ -10,8 +10,10 @@ import Database from '../sqlite.js';
|
|
|
10
10
|
import { getPerfDbPath, getPerfDir } from '../state.js';
|
|
11
11
|
import { localMachineId } from '../session/origin-machine.js';
|
|
12
12
|
import { resolveProjectKey } from '../project-key.js';
|
|
13
|
+
import { percentile } from '../percentile.js';
|
|
13
14
|
import { resolveSpoolPath, shortSessionId, _resetPerfSpoolForTest } from './spool.js';
|
|
14
15
|
export { recordSample, shortSessionId, resolveSpoolPath } from './spool.js';
|
|
16
|
+
export { percentile } from '../percentile.js';
|
|
15
17
|
export const PERF_SCHEMA_VERSION = 1;
|
|
16
18
|
export const DEFAULT_RETENTION_DAYS = 30;
|
|
17
19
|
const SCHEMA = `
|
|
@@ -186,20 +188,6 @@ function maybeRetain(db) {
|
|
|
186
188
|
// ignore
|
|
187
189
|
}
|
|
188
190
|
}
|
|
189
|
-
/** Percentile of a sorted-ascending array. p in [0,100]. */
|
|
190
|
-
export function percentile(sorted, p) {
|
|
191
|
-
if (sorted.length === 0)
|
|
192
|
-
return 0;
|
|
193
|
-
if (sorted.length === 1)
|
|
194
|
-
return sorted[0];
|
|
195
|
-
const rank = (p / 100) * (sorted.length - 1);
|
|
196
|
-
const lo = Math.floor(rank);
|
|
197
|
-
const hi = Math.ceil(rank);
|
|
198
|
-
if (lo === hi)
|
|
199
|
-
return sorted[lo];
|
|
200
|
-
const frac = rank - lo;
|
|
201
|
-
return sorted[lo] * (1 - frac) + sorted[hi] * frac;
|
|
202
|
-
}
|
|
203
191
|
/**
|
|
204
192
|
* Aggregate samples by (kind, label) with p50/p95/p99. Drains the spool first.
|
|
205
193
|
*
|
package/dist/lib/plugins.js
CHANGED
|
@@ -14,7 +14,7 @@ import * as yaml from 'yaml';
|
|
|
14
14
|
import { execFileSync } from 'child_process';
|
|
15
15
|
import { getPluginsDir, getTrashPluginsDir, getExtraPluginsDir, getProjectPluginsDir, getSystemPluginsDir } from './state.js';
|
|
16
16
|
import { IS_WINDOWS, isWindowsAbsolutePath, homeDir } from './platform/index.js';
|
|
17
|
-
import { assertSafeGitTransport } from './git.js';
|
|
17
|
+
import { assertSafeGitTransport, resolveSnapshotSha } from './git.js';
|
|
18
18
|
import { listInstalledVersions, getVersionHomePath } from './versions.js';
|
|
19
19
|
import { AGENTS, agentConfigDirName } from './agents.js';
|
|
20
20
|
import { capableAgents, isCapable } from './capabilities.js';
|
|
@@ -90,6 +90,13 @@ export function discoverPlugins(opts = {}) {
|
|
|
90
90
|
return out;
|
|
91
91
|
}
|
|
92
92
|
export function buildDiscoveredPlugin(pluginRoot, manifest, spec = { kind: 'user' }) {
|
|
93
|
+
// Every marketplace kind lays plugins out as `<repo>/plugins/<name>`, so the
|
|
94
|
+
// repo root is always the grandparent of pluginRoot — true for user
|
|
95
|
+
// (~/.agents), system (~/.agents/.system), each extra repo, and the project
|
|
96
|
+
// repo (<cwd>/.agents) alike. Deriving it here means every caller of
|
|
97
|
+
// buildDiscoveredPlugin (discoverPluginsInDir, inspectPluginCapabilities, …)
|
|
98
|
+
// gets provenance for free with no signature change.
|
|
99
|
+
const repoRoot = path.dirname(path.dirname(pluginRoot));
|
|
93
100
|
return {
|
|
94
101
|
name: manifest.name,
|
|
95
102
|
root: pluginRoot,
|
|
@@ -107,6 +114,10 @@ export function buildDiscoveredPlugin(pluginRoot, manifest, spec = { kind: 'user
|
|
|
107
114
|
monitors: discoverPluginMonitors(pluginRoot),
|
|
108
115
|
hasMcp: fs.existsSync(path.join(pluginRoot, '.mcp.json')),
|
|
109
116
|
hasSettings: pluginHasNonPermissionSettings(pluginRoot),
|
|
117
|
+
repoRoot,
|
|
118
|
+
get snapshotSha() {
|
|
119
|
+
return resolveSnapshotSha(repoRoot);
|
|
120
|
+
},
|
|
110
121
|
};
|
|
111
122
|
}
|
|
112
123
|
/**
|
package/dist/lib/resources.d.ts
CHANGED
|
@@ -16,6 +16,22 @@ export interface ResolvedResource {
|
|
|
16
16
|
* or the alias name (e.g. 'rush') for extra repos registered in agents.yaml.
|
|
17
17
|
*/
|
|
18
18
|
source: string;
|
|
19
|
+
/**
|
|
20
|
+
* Absolute path to the DotAgents repo root this resource resolved from (the
|
|
21
|
+
* project/user/system/extra-repo dir — one level above the `kind`
|
|
22
|
+
* subdirectory). DotAgents repos are git-tracked (plugins.ts), so this pairs
|
|
23
|
+
* with {@link snapshotSha} to answer "which commit of which repo".
|
|
24
|
+
*/
|
|
25
|
+
repoRoot: string;
|
|
26
|
+
/**
|
|
27
|
+
* Short HEAD sha of `repoRoot`'s git checkout, lazily resolved (a getter,
|
|
28
|
+
* not computed at construction) and memoized per repoRoot
|
|
29
|
+
* (`git.ts` `resolveSnapshotSha`) — a caller that never inspects provenance
|
|
30
|
+
* never pays for the git shell-out, and resolving many resources from the
|
|
31
|
+
* same repo pays for exactly one. `undefined` when `repoRoot` isn't a git
|
|
32
|
+
* repo (or has no commits).
|
|
33
|
+
*/
|
|
34
|
+
readonly snapshotSha: string | undefined;
|
|
19
35
|
}
|
|
20
36
|
/**
|
|
21
37
|
* True when `rawName` (a filename with its extension already stripped) names a
|
package/dist/lib/resources.js
CHANGED
|
@@ -15,6 +15,16 @@ import { WorkflowsHandler } from './resources/workflows.js';
|
|
|
15
15
|
import { isCapable } from './capabilities.js';
|
|
16
16
|
import { getProjectAgentsDir, getUserAgentsDir, getSystemAgentsDir, getEnabledExtraRepos, } from './state.js';
|
|
17
17
|
import { isNameActiveInResourceProfile } from './resource-profiles.js';
|
|
18
|
+
import { resolveSnapshotSha } from './git.js';
|
|
19
|
+
/** Build a ResolvedResource with a lazy, memoized `snapshotSha` getter. */
|
|
20
|
+
function withProvenance(base) {
|
|
21
|
+
return {
|
|
22
|
+
...base,
|
|
23
|
+
get snapshotSha() {
|
|
24
|
+
return resolveSnapshotSha(base.repoRoot);
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
18
28
|
function profiledKind(kind) {
|
|
19
29
|
switch (kind) {
|
|
20
30
|
case 'commands':
|
|
@@ -70,19 +80,19 @@ export function resolveResource(kind, name, cwd) {
|
|
|
70
80
|
const projectDir = getProjectAgentsDir(cwd);
|
|
71
81
|
const extraRepos = getEnabledExtraRepos();
|
|
72
82
|
const candidates = [
|
|
73
|
-
...(projectDir ? [[path.join(projectDir, kind), 'project']] : []),
|
|
74
|
-
[path.join(getUserAgentsDir(), kind), 'user'],
|
|
75
|
-
[path.join(getSystemAgentsDir(), kind), 'system'],
|
|
76
|
-
...extraRepos.map((e) => [path.join(e.dir, kind), e.alias]),
|
|
83
|
+
...(projectDir ? [[path.join(projectDir, kind), 'project', projectDir]] : []),
|
|
84
|
+
[path.join(getUserAgentsDir(), kind), 'user', getUserAgentsDir()],
|
|
85
|
+
[path.join(getSystemAgentsDir(), kind), 'system', getSystemAgentsDir()],
|
|
86
|
+
...extraRepos.map((e) => [path.join(e.dir, kind), e.alias, e.dir]),
|
|
77
87
|
];
|
|
78
|
-
for (const [dir, source] of candidates) {
|
|
88
|
+
for (const [dir, source, repoRoot] of candidates) {
|
|
79
89
|
if (!fs.existsSync(dir))
|
|
80
90
|
continue;
|
|
81
91
|
// Try exact name (for directories like skills/subagents)
|
|
82
92
|
const exactPath = path.join(dir, name);
|
|
83
93
|
if (fs.existsSync(exactPath)) {
|
|
84
94
|
if (resourceIsActive(kind, name, source)) {
|
|
85
|
-
return { name, path: exactPath, source };
|
|
95
|
+
return withProvenance({ name, path: exactPath, source, repoRoot });
|
|
86
96
|
}
|
|
87
97
|
continue;
|
|
88
98
|
}
|
|
@@ -94,7 +104,7 @@ export function resolveResource(kind, name, cwd) {
|
|
|
94
104
|
const withExt = exactPath + ext;
|
|
95
105
|
if (fs.existsSync(withExt)) {
|
|
96
106
|
if (resourceIsActive(kind, name, source)) {
|
|
97
|
-
return { name, path: withExt, source };
|
|
107
|
+
return withProvenance({ name, path: withExt, source, repoRoot });
|
|
98
108
|
}
|
|
99
109
|
continue;
|
|
100
110
|
}
|
|
@@ -113,12 +123,12 @@ export function listResources(kind, cwd) {
|
|
|
113
123
|
const projectDir = getProjectAgentsDir(cwd);
|
|
114
124
|
const extraRepos = getEnabledExtraRepos();
|
|
115
125
|
const roots = [
|
|
116
|
-
...(projectDir ? [[path.join(projectDir, kind), 'project']] : []),
|
|
117
|
-
[path.join(getUserAgentsDir(), kind), 'user'],
|
|
118
|
-
[path.join(getSystemAgentsDir(), kind), 'system'],
|
|
119
|
-
...extraRepos.map((e) => [path.join(e.dir, kind), e.alias]),
|
|
126
|
+
...(projectDir ? [[path.join(projectDir, kind), 'project', projectDir]] : []),
|
|
127
|
+
[path.join(getUserAgentsDir(), kind), 'user', getUserAgentsDir()],
|
|
128
|
+
[path.join(getSystemAgentsDir(), kind), 'system', getSystemAgentsDir()],
|
|
129
|
+
...extraRepos.map((e) => [path.join(e.dir, kind), e.alias, e.dir]),
|
|
120
130
|
];
|
|
121
|
-
for (const [dir, source] of roots) {
|
|
131
|
+
for (const [dir, source, repoRoot] of roots) {
|
|
122
132
|
if (!fs.existsSync(dir))
|
|
123
133
|
continue;
|
|
124
134
|
let entries;
|
|
@@ -143,11 +153,12 @@ export function listResources(kind, cwd) {
|
|
|
143
153
|
if (!resourceIsActive(kind, rawName, source))
|
|
144
154
|
continue;
|
|
145
155
|
seen.add(rawName);
|
|
146
|
-
results.push({
|
|
156
|
+
results.push(withProvenance({
|
|
147
157
|
name: rawName,
|
|
148
158
|
path: path.join(dir, entry.name),
|
|
149
159
|
source,
|
|
150
|
-
|
|
160
|
+
repoRoot,
|
|
161
|
+
}));
|
|
151
162
|
}
|
|
152
163
|
}
|
|
153
164
|
return results;
|
package/dist/lib/routines.js
CHANGED
|
@@ -16,6 +16,7 @@ import { atomicWriteFileSync } from './fs-atomic.js';
|
|
|
16
16
|
import { ALL_AGENT_IDS } from './agents.js';
|
|
17
17
|
import { machineId, normalizeHost } from './machine-id.js';
|
|
18
18
|
import { resolveActor } from './actor.js';
|
|
19
|
+
import { percentile } from './percentile.js';
|
|
19
20
|
export const HOST_STRATEGIES = ['local', 'host', 'fleet', 'cloud'];
|
|
20
21
|
/** Canonical set of accepted GitHub trigger events — single source for validation. */
|
|
21
22
|
export const GITHUB_TRIGGER_EVENTS = [
|
|
@@ -964,20 +965,6 @@ export function getLatestCompletedRun(jobName) {
|
|
|
964
965
|
}
|
|
965
966
|
return null;
|
|
966
967
|
}
|
|
967
|
-
/** Percentile of a sorted-ascending array (linear interpolation). p in [0,100]. */
|
|
968
|
-
function percentile(sorted, p) {
|
|
969
|
-
if (sorted.length === 0)
|
|
970
|
-
return 0;
|
|
971
|
-
if (sorted.length === 1)
|
|
972
|
-
return sorted[0];
|
|
973
|
-
const rank = (p / 100) * (sorted.length - 1);
|
|
974
|
-
const lo = Math.floor(rank);
|
|
975
|
-
const hi = Math.ceil(rank);
|
|
976
|
-
if (lo === hi)
|
|
977
|
-
return sorted[lo];
|
|
978
|
-
const frac = rank - lo;
|
|
979
|
-
return sorted[lo] * (1 - frac) + sorted[hi] * frac;
|
|
980
|
-
}
|
|
981
968
|
/**
|
|
982
969
|
* Fold a job's run history (`listRuns`) into a duration + outcome summary.
|
|
983
970
|
* `missed` fires (no process ever ran) carry no `duration` and are excluded
|
package/dist/lib/runner.js
CHANGED
|
@@ -66,7 +66,14 @@ const ROUTINE_TRANSCRIPT_SPECS = {
|
|
|
66
66
|
gemini: [{ root: ['.gemini', 'tmp'], ext: '.json' }],
|
|
67
67
|
antigravity: [{ root: ['.gemini', 'antigravity-cli', 'conversations'], ext: '.db' }],
|
|
68
68
|
droid: [{ root: ['.factory', 'sessions'], ext: '.jsonl' }],
|
|
69
|
-
|
|
69
|
+
// Kimi splits a session across two files (session/discover.ts:4382-4384):
|
|
70
|
+
// state.json (title/timestamps) and agents/main/wire.jsonl (the actual
|
|
71
|
+
// conversation). Both extensions are needed — .json alone archives only
|
|
72
|
+
// the metadata shell and silently drops every message.
|
|
73
|
+
kimi: [
|
|
74
|
+
{ root: ['.kimi-code', 'sessions'], ext: '.json' },
|
|
75
|
+
{ root: ['.kimi-code', 'sessions'], ext: '.jsonl' },
|
|
76
|
+
],
|
|
70
77
|
grok: [{ root: ['.grok', 'sessions'], ext: '.json' }],
|
|
71
78
|
};
|
|
72
79
|
/** Stable working directory for routine children, independent of the daemon's launch cwd. */
|
|
Binary file
|
|
Binary file
|
package/dist/lib/session/db.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type { SessionAgentId, SessionMeta } from './types.js';
|
|
|
11
11
|
/** Current schema version; bumped when migrations are added. Exported so tests
|
|
12
12
|
* assert against the constant instead of hardcoding a number that every bump
|
|
13
13
|
* then has to chase (docs/05-sessions.md calls the constant the source of truth). */
|
|
14
|
-
export declare const SCHEMA_VERSION =
|
|
14
|
+
export declare const SCHEMA_VERSION = 24;
|
|
15
15
|
/** Raw row shape returned from the sessions table. */
|
|
16
16
|
export interface SessionRow {
|
|
17
17
|
id: string;
|
|
@@ -54,6 +54,9 @@ export interface SessionRow {
|
|
|
54
54
|
linear_project_url: string | null;
|
|
55
55
|
actor: string | null;
|
|
56
56
|
initiated_by: string | null;
|
|
57
|
+
/** NULL means "not yet computed" (a row scanned before this field existed) — see rowToMeta. */
|
|
58
|
+
used_browser: number | null;
|
|
59
|
+
used_computer: number | null;
|
|
57
60
|
}
|
|
58
61
|
/** File stat snapshot used to detect changes between scan runs. */
|
|
59
62
|
export interface ScanStamp {
|
|
@@ -88,6 +91,18 @@ export interface QueryOptions {
|
|
|
88
91
|
* with NULLs sorted last so unpriced rows never crowd out real data.
|
|
89
92
|
*/
|
|
90
93
|
sortBy?: 'timestamp' | 'cost' | 'duration';
|
|
94
|
+
/**
|
|
95
|
+
* Only sessions that invoked this skill (#12), joined against
|
|
96
|
+
* session_resource_usage.kind='skill'. Matches either the full stored name
|
|
97
|
+
* (bare, or `plugin:name` for a plugin skill) or just the short name after
|
|
98
|
+
* the colon — `--skill design` finds a session that used `rush:design`.
|
|
99
|
+
*/
|
|
100
|
+
skill?: string;
|
|
101
|
+
/**
|
|
102
|
+
* Only sessions that used a skill or slash-command owned by this plugin
|
|
103
|
+
* (#12), joined against session_resource_usage.plugin.
|
|
104
|
+
*/
|
|
105
|
+
plugin?: string;
|
|
91
106
|
}
|
|
92
107
|
/** Open (or return the cached) sessions database, applying migrations as needed. */
|
|
93
108
|
export declare function getDB(): Database.Database;
|