@phnx-labs/agents-cli 1.14.7 → 1.16.0
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 +78 -39
- package/README.md +74 -7
- package/dist/commands/alias.js +2 -2
- package/dist/commands/beta.js +6 -1
- package/dist/commands/browser-picker.d.ts +21 -0
- package/dist/commands/browser-picker.js +114 -0
- package/dist/commands/browser.js +546 -75
- package/dist/commands/commands.js +72 -22
- package/dist/commands/daemon.js +2 -2
- package/dist/commands/exec.js +9 -2
- package/dist/commands/fork.js +2 -2
- package/dist/commands/hooks.js +71 -26
- package/dist/commands/mcp.js +85 -43
- package/dist/commands/plugins.js +48 -15
- package/dist/commands/prune.d.ts +0 -20
- package/dist/commands/prune.js +291 -16
- package/dist/commands/pull.js +3 -3
- package/dist/commands/repo.js +1 -1
- package/dist/commands/routines.js +2 -2
- package/dist/commands/secrets.js +37 -1
- package/dist/commands/sessions.js +62 -19
- package/dist/commands/{init.d.ts → setup.d.ts} +7 -6
- package/dist/commands/{init.js → setup.js} +32 -21
- package/dist/commands/skills.js +60 -19
- package/dist/commands/subagents.js +41 -13
- package/dist/commands/teams.js +2 -3
- package/dist/commands/usage.js +6 -0
- package/dist/commands/utils.d.ts +16 -0
- package/dist/commands/utils.js +32 -0
- package/dist/commands/versions.js +8 -6
- package/dist/commands/view.js +61 -16
- package/dist/index.d.ts +1 -1
- package/dist/index.js +17 -20
- package/dist/lib/agents.js +2 -2
- package/dist/lib/auto-pull-worker.js +2 -3
- package/dist/lib/auto-pull.js +2 -2
- package/dist/lib/browser/cdp.d.ts +7 -1
- package/dist/lib/browser/cdp.js +29 -1
- package/dist/lib/browser/chrome.js +6 -3
- package/dist/lib/browser/devices.d.ts +4 -0
- package/dist/lib/browser/devices.js +27 -0
- package/dist/lib/browser/drivers/local.js +9 -4
- package/dist/lib/browser/drivers/ssh.d.ts +1 -0
- package/dist/lib/browser/drivers/ssh.js +32 -4
- package/dist/lib/browser/ipc.js +145 -23
- package/dist/lib/browser/profiles.d.ts +5 -2
- package/dist/lib/browser/profiles.js +77 -37
- package/dist/lib/browser/service.d.ts +84 -13
- package/dist/lib/browser/service.js +806 -122
- package/dist/lib/browser/types.d.ts +81 -3
- package/dist/lib/browser/types.js +16 -0
- package/dist/lib/cloud/rush.js +2 -2
- package/dist/lib/cloud/store.js +2 -2
- package/dist/lib/commands.d.ts +1 -0
- package/dist/lib/commands.js +6 -2
- package/dist/lib/daemon.js +6 -7
- package/dist/lib/doctor-diff.js +4 -4
- package/dist/lib/events.d.ts +94 -1
- package/dist/lib/events.js +264 -6
- package/dist/lib/exec.js +16 -10
- package/dist/lib/hooks.d.ts +11 -7
- package/dist/lib/hooks.js +125 -49
- package/dist/lib/migrate.d.ts +1 -1
- package/dist/lib/migrate.js +1178 -21
- package/dist/lib/models.js +2 -2
- package/dist/lib/permissions.d.ts +14 -11
- package/dist/lib/permissions.js +46 -42
- package/dist/lib/plugins.d.ts +30 -1
- package/dist/lib/plugins.js +75 -3
- package/dist/lib/pty-server.js +9 -10
- package/dist/lib/resources/hooks.d.ts +5 -1
- package/dist/lib/resources/hooks.js +21 -4
- package/dist/lib/rotate.js +3 -4
- package/dist/lib/routines.d.ts +15 -0
- package/dist/lib/routines.js +68 -0
- package/dist/lib/runner.js +9 -5
- package/dist/lib/secrets/index.d.ts +14 -11
- package/dist/lib/secrets/index.js +49 -21
- package/dist/lib/secrets/linux.d.ts +27 -0
- package/dist/lib/secrets/linux.js +161 -0
- package/dist/lib/session/active.d.ts +3 -0
- package/dist/lib/session/active.js +92 -6
- package/dist/lib/session/cloud.js +2 -2
- package/dist/lib/session/db.d.ts +4 -0
- package/dist/lib/session/db.js +34 -3
- package/dist/lib/session/discover.js +30 -15
- package/dist/lib/session/team-filter.js +2 -2
- package/dist/lib/shims.d.ts +2 -2
- package/dist/lib/shims.js +6 -6
- package/dist/lib/skills.js +6 -2
- package/dist/lib/state.d.ts +86 -14
- package/dist/lib/state.js +150 -23
- package/dist/lib/subagents.d.ts +28 -0
- package/dist/lib/subagents.js +98 -1
- package/dist/lib/sync-manifest.d.ts +1 -1
- package/dist/lib/sync-manifest.js +3 -3
- package/dist/lib/teams/persistence.js +15 -5
- package/dist/lib/teams/registry.js +2 -2
- package/dist/lib/types.d.ts +32 -3
- package/dist/lib/types.js +3 -3
- package/dist/lib/usage.d.ts +1 -1
- package/dist/lib/usage.js +15 -48
- package/dist/lib/versions.js +31 -21
- package/package.json +1 -1
- package/scripts/postinstall.js +37 -9
|
@@ -16,12 +16,17 @@ export interface BrowserProfile {
|
|
|
16
16
|
export interface ChromeOptions {
|
|
17
17
|
headless?: boolean;
|
|
18
18
|
args?: string[];
|
|
19
|
+
viewport?: {
|
|
20
|
+
width: number;
|
|
21
|
+
height: number;
|
|
22
|
+
};
|
|
19
23
|
}
|
|
20
24
|
export interface Task {
|
|
21
25
|
id: string;
|
|
26
|
+
name: string;
|
|
22
27
|
profile: string;
|
|
23
|
-
|
|
24
|
-
|
|
28
|
+
tabs: Record<string, string>;
|
|
29
|
+
currentTabId?: string;
|
|
25
30
|
createdAt: number;
|
|
26
31
|
pid: number;
|
|
27
32
|
}
|
|
@@ -36,17 +41,39 @@ export interface ProfileStatus {
|
|
|
36
41
|
running: boolean;
|
|
37
42
|
port?: number;
|
|
38
43
|
pid?: number;
|
|
44
|
+
/** The port declared in the profile's first endpoint, when it differs from the running port. */
|
|
45
|
+
configuredPort?: number;
|
|
39
46
|
tasks: TaskStatus[];
|
|
40
47
|
}
|
|
41
48
|
export interface TaskStatus {
|
|
42
49
|
id: string;
|
|
50
|
+
name: string;
|
|
43
51
|
tabCount: number;
|
|
52
|
+
currentTabId?: string;
|
|
44
53
|
createdAt: number;
|
|
54
|
+
endedAt?: number;
|
|
55
|
+
domains?: string[];
|
|
56
|
+
tabs?: Array<{
|
|
57
|
+
id: string;
|
|
58
|
+
url: string;
|
|
59
|
+
title?: string;
|
|
60
|
+
current?: boolean;
|
|
61
|
+
}>;
|
|
45
62
|
}
|
|
46
|
-
export
|
|
63
|
+
export interface HistoricalTask {
|
|
64
|
+
id: string;
|
|
65
|
+
name: string;
|
|
66
|
+
profile: string;
|
|
67
|
+
createdAt: number;
|
|
68
|
+
endedAt: number;
|
|
69
|
+
domains: string[];
|
|
70
|
+
tabCount: number;
|
|
71
|
+
}
|
|
72
|
+
export type IPCAction = 'start' | 'done' | 'stop' | 'status' | 'history' | 'navigate' | 'tab-add' | 'tab-focus' | 'tab-close' | 'tab-list' | 'evaluate' | 'screenshot' | 'refs' | 'click' | 'type' | 'press' | 'hover' | 'set-viewport' | 'set-device' | 'console' | 'errors' | 'requests' | 'response-body' | 'wait' | 'set-download-path' | 'wait-download';
|
|
47
73
|
export interface IPCRequest {
|
|
48
74
|
action: IPCAction;
|
|
49
75
|
task?: string;
|
|
76
|
+
taskName?: string;
|
|
50
77
|
profile?: string;
|
|
51
78
|
url?: string;
|
|
52
79
|
tabId?: string;
|
|
@@ -57,6 +84,20 @@ export interface IPCRequest {
|
|
|
57
84
|
key?: string;
|
|
58
85
|
interactive?: boolean;
|
|
59
86
|
limit?: number;
|
|
87
|
+
width?: number;
|
|
88
|
+
height?: number;
|
|
89
|
+
deviceName?: string;
|
|
90
|
+
mobile?: boolean;
|
|
91
|
+
deviceScaleFactor?: number;
|
|
92
|
+
level?: 'log' | 'info' | 'warn' | 'error';
|
|
93
|
+
clear?: boolean;
|
|
94
|
+
filter?: string;
|
|
95
|
+
urlPattern?: string;
|
|
96
|
+
maxChars?: number;
|
|
97
|
+
waitType?: 'time' | 'selector' | 'url' | 'function' | 'load';
|
|
98
|
+
waitValue?: string | number;
|
|
99
|
+
timeout?: number;
|
|
100
|
+
downloadPath?: string;
|
|
60
101
|
}
|
|
61
102
|
export interface IPCResponse {
|
|
62
103
|
ok: boolean;
|
|
@@ -66,10 +107,47 @@ export interface IPCResponse {
|
|
|
66
107
|
windowTargetId?: string;
|
|
67
108
|
tabs?: TabInfo[];
|
|
68
109
|
profiles?: ProfileStatus[];
|
|
110
|
+
history?: HistoricalTask[];
|
|
69
111
|
result?: unknown;
|
|
70
112
|
path?: string;
|
|
71
113
|
refs?: string;
|
|
114
|
+
logs?: ConsoleEntry[];
|
|
115
|
+
errors?: ErrorEntry[];
|
|
116
|
+
requests?: NetworkRequest[];
|
|
117
|
+
body?: string;
|
|
118
|
+
downloadPath?: string;
|
|
119
|
+
devices?: string[];
|
|
120
|
+
}
|
|
121
|
+
export interface ConsoleEntry {
|
|
122
|
+
level: 'log' | 'info' | 'warn' | 'error';
|
|
123
|
+
text: string;
|
|
124
|
+
timestamp: number;
|
|
125
|
+
url?: string;
|
|
126
|
+
line?: number;
|
|
127
|
+
}
|
|
128
|
+
export interface ErrorEntry {
|
|
129
|
+
message: string;
|
|
130
|
+
stack?: string;
|
|
131
|
+
timestamp: number;
|
|
132
|
+
url?: string;
|
|
133
|
+
line?: number;
|
|
134
|
+
}
|
|
135
|
+
export interface NetworkRequest {
|
|
136
|
+
id: string;
|
|
137
|
+
url: string;
|
|
138
|
+
method: string;
|
|
139
|
+
status?: number;
|
|
140
|
+
mimeType?: string;
|
|
141
|
+
timestamp: number;
|
|
142
|
+
}
|
|
143
|
+
export interface DeviceDescriptor {
|
|
144
|
+
width: number;
|
|
145
|
+
height: number;
|
|
146
|
+
deviceScaleFactor: number;
|
|
147
|
+
mobile: boolean;
|
|
72
148
|
}
|
|
73
149
|
export declare const TASK_ID_REGEX: RegExp;
|
|
74
150
|
export declare function isValidTaskId(id: string): boolean;
|
|
75
151
|
export declare function generateTaskId(): string;
|
|
152
|
+
export declare function generateShortId(): string;
|
|
153
|
+
export declare function generateFunName(): string;
|
|
@@ -5,3 +5,19 @@ export function isValidTaskId(id) {
|
|
|
5
5
|
export function generateTaskId() {
|
|
6
6
|
return crypto.randomUUID().slice(0, 8);
|
|
7
7
|
}
|
|
8
|
+
export function generateShortId() {
|
|
9
|
+
return crypto.randomUUID().split('-')[0]; // 8 chars
|
|
10
|
+
}
|
|
11
|
+
const ADJECTIVES = [
|
|
12
|
+
'swift', 'cosmic', 'jolly', 'quiet', 'bold', 'bright', 'calm', 'eager',
|
|
13
|
+
'golden', 'happy', 'keen', 'lucky', 'noble', 'proud', 'quick', 'royal',
|
|
14
|
+
];
|
|
15
|
+
const NOUNS = [
|
|
16
|
+
'falcon', 'comet', 'tiger', 'nebula', 'phoenix', 'river', 'summit', 'wave',
|
|
17
|
+
'aurora', 'breeze', 'crystal', 'dragon', 'ember', 'forest', 'glacier', 'harbor',
|
|
18
|
+
];
|
|
19
|
+
export function generateFunName() {
|
|
20
|
+
const adj = ADJECTIVES[Math.floor(Math.random() * ADJECTIVES.length)];
|
|
21
|
+
const noun = NOUNS[Math.floor(Math.random() * NOUNS.length)];
|
|
22
|
+
return `${adj}-${noun}`;
|
|
23
|
+
}
|
package/dist/lib/cloud/rush.js
CHANGED
|
@@ -9,7 +9,7 @@ import * as path from 'path';
|
|
|
9
9
|
import * as os from 'os';
|
|
10
10
|
import * as crypto from 'crypto';
|
|
11
11
|
import * as yaml from 'yaml';
|
|
12
|
-
import {
|
|
12
|
+
import { getCloudDir } from '../state.js';
|
|
13
13
|
import { resolveDispatchRepos } from './types.js';
|
|
14
14
|
import { parseSSE } from './stream.js';
|
|
15
15
|
import { listInstalledVersions, getVersionHomePath } from '../versions.js';
|
|
@@ -20,7 +20,7 @@ const USER_YAML = path.join(os.homedir(), '.rush', 'user.yaml');
|
|
|
20
20
|
// Persistent consent record for uploading Claude OAuth blobs to Rush Cloud.
|
|
21
21
|
// Created on first explicit consent (env var or flag); subsequent dispatches
|
|
22
22
|
// see it and proceed without re-prompting.
|
|
23
|
-
const RUSH_CONSENT_PATH = path.join(
|
|
23
|
+
const RUSH_CONSENT_PATH = path.join(getCloudDir(), 'rush-consent.json');
|
|
24
24
|
const RUSH_CONSENT_ENV = 'AGENTS_RUSH_UPLOAD_TOKENS';
|
|
25
25
|
function hasRushUploadConsent(opts) {
|
|
26
26
|
if (process.env[RUSH_CONSENT_ENV] === '1')
|
package/dist/lib/cloud/store.js
CHANGED
|
@@ -8,8 +8,8 @@
|
|
|
8
8
|
import * as fs from 'fs';
|
|
9
9
|
import * as path from 'path';
|
|
10
10
|
import Database from '../sqlite.js';
|
|
11
|
-
import {
|
|
12
|
-
const CLOUD_DIR =
|
|
11
|
+
import { getCloudDir } from '../state.js';
|
|
12
|
+
const CLOUD_DIR = getCloudDir();
|
|
13
13
|
const DB_PATH = path.join(CLOUD_DIR, 'tasks.db');
|
|
14
14
|
const SCHEMA = `
|
|
15
15
|
CREATE TABLE IF NOT EXISTS tasks (
|
package/dist/lib/commands.d.ts
CHANGED
|
@@ -79,6 +79,7 @@ export declare function installCommandToVersion(agent: AgentId, version: string,
|
|
|
79
79
|
};
|
|
80
80
|
/**
|
|
81
81
|
* Remove a single command from a specific version home.
|
|
82
|
+
* Soft-deletes to ~/.agents/.trash/commands/.
|
|
82
83
|
*/
|
|
83
84
|
export declare function removeCommandFromVersion(agent: AgentId, version: string, commandName: string): {
|
|
84
85
|
success: boolean;
|
package/dist/lib/commands.js
CHANGED
|
@@ -11,7 +11,7 @@ import * as path from 'path';
|
|
|
11
11
|
import * as yaml from 'yaml';
|
|
12
12
|
import { AGENTS, COMMANDS_CAPABLE_AGENTS, ensureCommandsDir } from './agents.js';
|
|
13
13
|
import { markdownToToml } from './convert.js';
|
|
14
|
-
import { getCommandsDir, getUserCommandsDir, getEnabledExtraRepos, getProjectAgentsDir, getSkillsDir } from './state.js';
|
|
14
|
+
import { getCommandsDir, getUserCommandsDir, getEnabledExtraRepos, getProjectAgentsDir, getSkillsDir, getTrashCommandsDir } from './state.js';
|
|
15
15
|
import { getEffectiveHome, getVersionHomePath, listInstalledVersions } from './versions.js';
|
|
16
16
|
import { commandSkillMatches, installCommandSkillToVersion, listCommandSkillsInVersion, removeCommandSkillFromVersion, shouldInstallCommandAsSkill, } from './command-skills.js';
|
|
17
17
|
/** Parse command metadata (name, description) from YAML frontmatter or TOML headers. */
|
|
@@ -279,6 +279,7 @@ export function installCommandToVersion(agent, version, commandName, method = 'c
|
|
|
279
279
|
}
|
|
280
280
|
/**
|
|
281
281
|
* Remove a single command from a specific version home.
|
|
282
|
+
* Soft-deletes to ~/.agents/.trash/commands/.
|
|
282
283
|
*/
|
|
283
284
|
export function removeCommandFromVersion(agent, version, commandName) {
|
|
284
285
|
const versionHome = getVersionHomePath(agent, version);
|
|
@@ -292,7 +293,10 @@ export function removeCommandFromVersion(agent, version, commandName) {
|
|
|
292
293
|
return { success: true };
|
|
293
294
|
}
|
|
294
295
|
try {
|
|
295
|
-
|
|
296
|
+
const stamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
297
|
+
const trashDir = path.join(getTrashCommandsDir(), agent, version, commandName);
|
|
298
|
+
fs.mkdirSync(trashDir, { recursive: true, mode: 0o700 });
|
|
299
|
+
fs.renameSync(targetPath, path.join(trashDir, `${commandName}${ext}.${stamp}`));
|
|
296
300
|
}
|
|
297
301
|
catch (err) {
|
|
298
302
|
return { success: false, error: err.message };
|
package/dist/lib/daemon.js
CHANGED
|
@@ -6,17 +6,16 @@
|
|
|
6
6
|
* (macOS), systemd (Linux), or as a plain detached process. PID tracking,
|
|
7
7
|
* log output, reload (SIGHUP), and graceful shutdown are handled here.
|
|
8
8
|
*/
|
|
9
|
-
import { spawn, execSync } from 'child_process';
|
|
9
|
+
import { spawn, execSync, execFileSync } from 'child_process';
|
|
10
10
|
import * as fs from 'fs';
|
|
11
11
|
import * as path from 'path';
|
|
12
12
|
import * as os from 'os';
|
|
13
|
-
import {
|
|
13
|
+
import { getDaemonDir as getDaemonDirRoot } from './state.js';
|
|
14
14
|
import { listJobs as listAllJobs } from './routines.js';
|
|
15
15
|
import { JobScheduler } from './scheduler.js';
|
|
16
16
|
import { executeJobDetached, monitorRunningJobs } from './runner.js';
|
|
17
17
|
import { BrowserService } from './browser/service.js';
|
|
18
18
|
import { BrowserIPCServer } from './browser/ipc.js';
|
|
19
|
-
const DAEMON_DIR = 'helpers/daemon';
|
|
20
19
|
const PID_FILE = 'daemon.pid';
|
|
21
20
|
const LOCK_FILE = 'daemon.lock';
|
|
22
21
|
const LOG_FILE = 'logs.jsonl';
|
|
@@ -25,7 +24,7 @@ const LOG_ROTATE_COUNT = 3;
|
|
|
25
24
|
const PLIST_NAME = 'com.phnx-labs.agents-daemon';
|
|
26
25
|
const SYSTEMD_UNIT = 'agents-daemon.service';
|
|
27
26
|
function getDaemonDir() {
|
|
28
|
-
const dir =
|
|
27
|
+
const dir = getDaemonDirRoot();
|
|
29
28
|
fs.mkdirSync(dir, { recursive: true });
|
|
30
29
|
return dir;
|
|
31
30
|
}
|
|
@@ -297,10 +296,10 @@ function startDaemonLocked() {
|
|
|
297
296
|
}
|
|
298
297
|
fs.writeFileSync(plistPath, generateLaunchdPlist(), 'utf-8');
|
|
299
298
|
try {
|
|
300
|
-
|
|
299
|
+
execFileSync('launchctl', ['unload', plistPath], { encoding: 'utf-8', stdio: ['ignore', 'pipe', 'ignore'] });
|
|
301
300
|
}
|
|
302
301
|
catch { /* not loaded, expected */ }
|
|
303
|
-
|
|
302
|
+
execFileSync('launchctl', ['load', plistPath], { encoding: 'utf-8' });
|
|
304
303
|
const pid = waitForPid(3000);
|
|
305
304
|
return { pid, method: 'launchd' };
|
|
306
305
|
}
|
|
@@ -358,7 +357,7 @@ export function stopDaemon() {
|
|
|
358
357
|
const plistPath = getLaunchdPlistPath();
|
|
359
358
|
if (fs.existsSync(plistPath)) {
|
|
360
359
|
try {
|
|
361
|
-
|
|
360
|
+
execFileSync('launchctl', ['unload', plistPath], { encoding: 'utf-8' });
|
|
362
361
|
fs.unlinkSync(plistPath);
|
|
363
362
|
}
|
|
364
363
|
catch (err) {
|
package/dist/lib/doctor-diff.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
import * as fs from 'fs';
|
|
23
23
|
import * as path from 'path';
|
|
24
24
|
import { AGENTS } from './agents.js';
|
|
25
|
-
import { getProjectAgentsDir, getUserAgentsDir, getSystemAgentsDir, getEnabledExtraRepos, getResolvedRulesDir, getUserRulesDir,
|
|
25
|
+
import { getProjectAgentsDir, getUserAgentsDir, getSystemAgentsDir, getEnabledExtraRepos, getResolvedRulesDir, getUserRulesDir, getEffectivePromptcutsPath, } from './state.js';
|
|
26
26
|
import { getAvailableResources, getActuallySyncedResources, getVersionHomePath, } from './versions.js';
|
|
27
27
|
import { markdownToToml } from './convert.js';
|
|
28
28
|
import { resolveImports, supportsRulesImports } from './rules/compile.js';
|
|
@@ -426,10 +426,10 @@ function diffPresenceOnly(kind, available, synced) {
|
|
|
426
426
|
return rows.sort((a, b) => a.name.localeCompare(b.name));
|
|
427
427
|
}
|
|
428
428
|
function diffPromptcuts() {
|
|
429
|
-
const
|
|
430
|
-
if (!
|
|
429
|
+
const sourcePath = getEffectivePromptcutsPath();
|
|
430
|
+
if (!fs.existsSync(sourcePath))
|
|
431
431
|
return [];
|
|
432
|
-
return [{ kind: 'promptcuts', name: 'promptcuts.yaml', status: 'ok', sourcePath
|
|
432
|
+
return [{ kind: 'promptcuts', name: 'promptcuts.yaml', status: 'ok', sourcePath }];
|
|
433
433
|
}
|
|
434
434
|
export function diffVersionResources(agent, version, options = {}) {
|
|
435
435
|
const cwd = options.cwd ?? process.cwd();
|
package/dist/lib/events.d.ts
CHANGED
|
@@ -3,8 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Structured JSONL logs at ~/.agents/logs/events-YYYY-MM-DD.jsonl
|
|
5
5
|
* with automatic daily rotation and rich metadata for debugging/auditing.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Rich metadata: hostname, platform, arch, pid, timezone
|
|
9
|
+
* - Timing helpers: measure operation duration automatically
|
|
10
|
+
* - Truncation: long inputs/outputs are trimmed with ellipsis
|
|
11
|
+
* - Permissions: logs dir is 0700, files are 0600 (owner-only)
|
|
12
|
+
* - Performance tracking: withTiming() wrapper for any async function
|
|
6
13
|
*/
|
|
7
|
-
export type EventType = 'agent.run.start' | 'agent.run.end' | 'version.install' | 'version.switch' | 'version.remove' | 'skill.install' | 'skill.remove' | 'browser.launch' | 'browser.close' | 'secrets.get' | 'secrets.set' | 'secrets.delete' | 'cloud.dispatch' | 'cloud.complete' | 'teams.create' | 'teams.start' | 'teams.complete' | 'hook.fire' | 'hook.error' | 'resource.sync' | 'error' | 'warn' | 'info';
|
|
14
|
+
export type EventType = 'agent.run.start' | 'agent.run.end' | 'agent.spawn.start' | 'agent.spawn.end' | 'version.install' | 'version.switch' | 'version.remove' | 'skill.install' | 'skill.remove' | 'browser.launch' | 'browser.close' | 'browser.navigate' | 'browser.screenshot' | 'secrets.get' | 'secrets.set' | 'secrets.delete' | 'cloud.dispatch' | 'cloud.complete' | 'teams.create' | 'teams.add' | 'teams.start' | 'teams.complete' | 'hook.fire' | 'hook.complete' | 'hook.error' | 'resource.sync' | 'command.start' | 'command.end' | 'perf.timing' | 'session.start' | 'session.end' | 'error' | 'warn' | 'info' | 'debug';
|
|
8
15
|
export interface EventMeta {
|
|
9
16
|
ts: string;
|
|
10
17
|
tz: string;
|
|
@@ -13,17 +20,33 @@ export interface EventMeta {
|
|
|
13
20
|
platform: NodeJS.Platform;
|
|
14
21
|
arch: string;
|
|
15
22
|
pid: number;
|
|
23
|
+
ppid: number;
|
|
16
24
|
event: EventType;
|
|
17
25
|
}
|
|
18
26
|
export interface EventPayload {
|
|
19
27
|
agent?: string;
|
|
20
28
|
version?: string;
|
|
29
|
+
sessionId?: string;
|
|
21
30
|
cwd?: string;
|
|
31
|
+
command?: string;
|
|
32
|
+
args?: string[];
|
|
33
|
+
input?: string;
|
|
34
|
+
output?: string;
|
|
35
|
+
prompt?: string;
|
|
22
36
|
durationMs?: number;
|
|
37
|
+
startupMs?: number;
|
|
38
|
+
exitCode?: number;
|
|
39
|
+
status?: string;
|
|
23
40
|
error?: string;
|
|
41
|
+
errorStack?: string;
|
|
24
42
|
[key: string]: unknown;
|
|
25
43
|
}
|
|
26
44
|
export type EventRecord = EventMeta & EventPayload;
|
|
45
|
+
/**
|
|
46
|
+
* Truncate a string to maxLength, adding ellipsis if truncated.
|
|
47
|
+
* Returns undefined for null/undefined input.
|
|
48
|
+
*/
|
|
49
|
+
export declare function truncate(str: string | null | undefined, maxLength?: number): string | undefined;
|
|
27
50
|
/**
|
|
28
51
|
* Emit a structured event to the daily log file.
|
|
29
52
|
*
|
|
@@ -41,6 +64,62 @@ export declare function emit(event: EventType, payload?: EventPayload): void;
|
|
|
41
64
|
* done({ exitCode: 0 }); // emits agent.run.end with durationMs
|
|
42
65
|
*/
|
|
43
66
|
export declare function emitStart(startEvent: EventType, payload?: EventPayload): (endPayload?: EventPayload) => void;
|
|
67
|
+
/**
|
|
68
|
+
* Measure execution time of a synchronous function.
|
|
69
|
+
* Emits a perf.timing event with the duration.
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* const result = time('parse-config', () => parseConfig(path));
|
|
73
|
+
*/
|
|
74
|
+
export declare function time<T>(label: string, fn: () => T, payload?: EventPayload): T;
|
|
75
|
+
/**
|
|
76
|
+
* Measure execution time of an async function.
|
|
77
|
+
* Emits a perf.timing event with the duration.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* const result = await timeAsync('fetch-data', () => fetchData(url));
|
|
81
|
+
*/
|
|
82
|
+
export declare function timeAsync<T>(label: string, fn: () => Promise<T>, payload?: EventPayload): Promise<T>;
|
|
83
|
+
/**
|
|
84
|
+
* Create a timing context for measuring multiple phases of an operation.
|
|
85
|
+
* Useful for tracking startup time vs execution time.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* const timer = createTimer('agent.run', { agent: 'claude' });
|
|
89
|
+
* // ... setup work ...
|
|
90
|
+
* timer.mark('startup'); // records startup time
|
|
91
|
+
* // ... main work ...
|
|
92
|
+
* timer.end({ exitCode: 0 }); // records total time and emits event
|
|
93
|
+
*/
|
|
94
|
+
export declare function createTimer(label: string, payload?: EventPayload): {
|
|
95
|
+
mark: (phase: string) => number;
|
|
96
|
+
end: (endPayload?: EventPayload) => void;
|
|
97
|
+
elapsed: () => number;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Higher-order function that wraps an async function with timing.
|
|
101
|
+
* The wrapper emits start/end events automatically.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* const timedFetch = withTiming('fetch', fetchData, { service: 'api' });
|
|
105
|
+
* const result = await timedFetch(url);
|
|
106
|
+
*/
|
|
107
|
+
export declare function withTiming<Args extends unknown[], R>(label: string, fn: (...args: Args) => Promise<R>, basePayload?: EventPayload): (...args: Args) => Promise<R>;
|
|
108
|
+
/**
|
|
109
|
+
* Emit a command.start event with CLI args.
|
|
110
|
+
* Returns a done() function to emit command.end with duration.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* // At CLI entry point:
|
|
114
|
+
* const done = emitCommand('run', process.argv.slice(2));
|
|
115
|
+
* // ... execute command ...
|
|
116
|
+
* done({ exitCode: 0 });
|
|
117
|
+
*/
|
|
118
|
+
export declare function emitCommand(command: string, args?: string[], payload?: EventPayload): (endPayload?: EventPayload) => void;
|
|
119
|
+
/**
|
|
120
|
+
* Emit an error event with full details.
|
|
121
|
+
*/
|
|
122
|
+
export declare function emitError(err: Error | string, payload?: EventPayload): void;
|
|
44
123
|
/**
|
|
45
124
|
* Remove log files older than the retention period.
|
|
46
125
|
* Called lazily on emit or explicitly via CLI.
|
|
@@ -61,6 +140,20 @@ export declare function query(options: {
|
|
|
61
140
|
endDate?: Date;
|
|
62
141
|
eventTypes?: EventType[];
|
|
63
142
|
agent?: string;
|
|
143
|
+
command?: string;
|
|
64
144
|
limit?: number;
|
|
65
145
|
}): EventRecord[];
|
|
146
|
+
/**
|
|
147
|
+
* Get performance stats for a specific label.
|
|
148
|
+
*/
|
|
149
|
+
export declare function getTimingStats(label: string, options?: {
|
|
150
|
+
days?: number;
|
|
151
|
+
}): {
|
|
152
|
+
count: number;
|
|
153
|
+
avgMs: number;
|
|
154
|
+
minMs: number;
|
|
155
|
+
maxMs: number;
|
|
156
|
+
p50Ms: number;
|
|
157
|
+
p95Ms: number;
|
|
158
|
+
} | null;
|
|
66
159
|
export declare const LOGS_PATH: string;
|