forkit-connect 0.1.5 → 0.1.7

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.
@@ -0,0 +1,15 @@
1
+ export interface HardwareMetrics {
2
+ cpu_percent: number;
3
+ vram_mb: number;
4
+ }
5
+ export declare class ResourceMeter {
6
+ constructor();
7
+ private snapshotCpuTicks;
8
+ private measureCpuPercent;
9
+ /**
10
+ * Captures generalized CPU & VRAM metadata for the system bounds.
11
+ * Native mapping to 'nvidia-smi' exposes exact VRAM allocations.
12
+ */
13
+ captureMetrics(targetProcessPath?: string): Promise<HardwareMetrics>;
14
+ }
15
+ //# sourceMappingURL=resource-meter.d.ts.map
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.ResourceMeter = void 0;
7
+ const child_process_1 = require("child_process");
8
+ const node_os_1 = __importDefault(require("node:os"));
9
+ const util_1 = require("util");
10
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
11
+ class ResourceMeter {
12
+ constructor() { }
13
+ snapshotCpuTicks() {
14
+ const cores = node_os_1.default.cpus();
15
+ let idle = 0;
16
+ let total = 0;
17
+ for (const core of cores) {
18
+ const times = core.times;
19
+ idle += times.idle;
20
+ total += times.user + times.nice + times.sys + times.idle + times.irq;
21
+ }
22
+ return { idle, total };
23
+ }
24
+ async measureCpuPercent(sampleMs = 180) {
25
+ const start = this.snapshotCpuTicks();
26
+ await new Promise((resolve) => setTimeout(resolve, sampleMs));
27
+ const end = this.snapshotCpuTicks();
28
+ const idleDelta = end.idle - start.idle;
29
+ const totalDelta = end.total - start.total;
30
+ if (totalDelta <= 0)
31
+ return 0;
32
+ const busyRatio = 1 - (idleDelta / totalDelta);
33
+ return Math.max(0, Math.min(100, busyRatio * 100));
34
+ }
35
+ /**
36
+ * Captures generalized CPU & VRAM metadata for the system bounds.
37
+ * Native mapping to 'nvidia-smi' exposes exact VRAM allocations.
38
+ */
39
+ async captureMetrics(targetProcessPath) {
40
+ let vram_mb = 0;
41
+ let cpu_percent = 0;
42
+ try {
43
+ cpu_percent = await this.measureCpuPercent();
44
+ // Attempt explicit native `nvidia-smi` read
45
+ const { stdout } = await execAsync('nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits');
46
+ if (stdout && stdout.trim()) {
47
+ const mems = stdout.split('\n').map(m => parseInt(m.trim())).filter(m => !isNaN(m));
48
+ if (mems.length > 0) {
49
+ vram_mb = mems.reduce((a, b) => a + b, 0);
50
+ }
51
+ }
52
+ }
53
+ catch (e) {
54
+ // Graceful drop to zero if no explicit hardware bindings exist
55
+ }
56
+ return { cpu_percent, vram_mb };
57
+ }
58
+ }
59
+ exports.ResourceMeter = ResourceMeter;
60
+ //# sourceMappingURL=resource-meter.js.map
package/dist/v1/api.d.ts CHANGED
@@ -95,6 +95,7 @@ export interface ProductSummaryResponse {
95
95
  } | null;
96
96
  runtimeSignals?: {
97
97
  runtimeSignalsPerMonth?: number | null;
98
+ maxRuntimeSubjects?: number | null;
98
99
  } | null;
99
100
  } | null;
100
101
  entitlements?: {
@@ -105,6 +106,7 @@ export interface ProductSummaryResponse {
105
106
  maxProjects?: number | null;
106
107
  maxWorkspaces?: number | null;
107
108
  maxGovernedPassports?: number | null;
109
+ maxRuntimeSubjects?: number | null;
108
110
  } | null;
109
111
  usage?: {
110
112
  passports?: number | null;
@@ -114,6 +116,41 @@ export interface ProductSummaryResponse {
114
116
  runtimeSignals?: number | null;
115
117
  } | null;
116
118
  }
119
+ export interface RuntimeResponse {
120
+ id?: number | string | null;
121
+ gaid?: string | null;
122
+ name?: string | null;
123
+ passportType?: string | null;
124
+ workspaceId?: string | null;
125
+ projectId?: string | null;
126
+ connectionStatus?: string | null;
127
+ sourceUrl?: string | null;
128
+ metadata?: Record<string, unknown> | null;
129
+ }
130
+ export interface RuntimeListResponse {
131
+ runtimes?: RuntimeResponse[];
132
+ total?: number | null;
133
+ runtimeLimit?: number | null;
134
+ usage?: {
135
+ runtimeSubjects?: number | null;
136
+ } | null;
137
+ }
138
+ export interface RuntimeCreateResponse {
139
+ runtime?: RuntimeResponse | null;
140
+ tier?: string | null;
141
+ runtimeLimit?: number | null;
142
+ usage?: {
143
+ runtimeSubjects?: number | null;
144
+ } | null;
145
+ }
146
+ export interface ApiKeyCreateResponse {
147
+ gaid?: string | null;
148
+ keyId?: string | null;
149
+ label?: string | null;
150
+ createdAt?: string | null;
151
+ rawKey?: string | null;
152
+ _warning?: string | null;
153
+ }
117
154
  export interface WorkspaceProject {
118
155
  id?: string | null;
119
156
  workspaceId?: string | null;
@@ -294,6 +331,8 @@ export declare class ConnectApiClient {
294
331
  getPassportsMine(limit?: number): Promise<ApiCallResult>;
295
332
  getProductSummary(): Promise<ApiCallResult>;
296
333
  createPassportDraft(payload: Record<string, unknown>): Promise<ApiCallResult>;
334
+ getRuntimesMine(limit?: number): Promise<ApiCallResult>;
335
+ createRuntime(payload: Record<string, unknown>): Promise<ApiCallResult>;
297
336
  pushRuntimeSignalEvent(payload: Record<string, unknown>): Promise<ApiCallResult>;
298
337
  pushRuntimeRunLog(payload: Record<string, unknown>): Promise<ApiCallResult>;
299
338
  getDeployments(gaid: string, scope?: DeploymentScopeQuery): Promise<ApiCallResult>;
@@ -305,6 +344,7 @@ export declare class ConnectApiClient {
305
344
  resumeDeploymentSession(gaid: string, sessionId: string, payload?: DeploymentSessionControlRequest, scope?: DeploymentScopeQuery): Promise<ApiCallResult>;
306
345
  revokeDeploymentSession(gaid: string, sessionId: string, payload?: DeploymentSessionControlRequest, scope?: DeploymentScopeQuery): Promise<ApiCallResult>;
307
346
  sendDeploymentCheckin(gaid: string, payload: DeploymentCheckinRequest): Promise<ApiCallResult>;
347
+ sendRuntimeCheckin(gaid: string, payload: DeploymentCheckinRequest, sessionId?: string | null): Promise<ApiCallResult>;
308
348
  getProfileAccess(): Promise<ApiCallResult>;
309
349
  getWorkspaceProjects(workspaceId: string): Promise<ApiCallResult>;
310
350
  createWorkspace(payload: {
@@ -332,6 +372,7 @@ export declare class ConnectApiClient {
332
372
  * owned passport. Returns the rawKey exactly once — caller must persist it.
333
373
  */
334
374
  createPassportApiKey(gaid: string, label?: string): Promise<ApiCallResult>;
375
+ createRuntimeApiKey(gaid: string, label?: string): Promise<ApiCallResult>;
335
376
  private parseBody;
336
377
  }
337
378
  //# sourceMappingURL=api.d.ts.map
package/dist/v1/api.js CHANGED
@@ -138,6 +138,34 @@ class ConnectApiClient {
138
138
  contract: this.parseContract(res),
139
139
  };
140
140
  }
141
+ async getRuntimesMine(limit = 100) {
142
+ const safeLimit = Math.min(Math.max(Math.trunc(Number(limit) || 100), 1), 100);
143
+ const url = `${this.config.baseUrl}/api/v1/runtimes/mine?limit=${safeLimit}`;
144
+ const res = await fetch(url, {
145
+ method: 'GET',
146
+ headers: this.getHeaders(),
147
+ });
148
+ return {
149
+ ok: res.ok,
150
+ status: res.status,
151
+ body: await this.parseBody(res),
152
+ contract: this.parseContract(res),
153
+ };
154
+ }
155
+ async createRuntime(payload) {
156
+ const url = `${this.config.baseUrl}/api/v1/runtimes`;
157
+ const res = await fetch(url, {
158
+ method: 'POST',
159
+ headers: this.getHeaders(),
160
+ body: JSON.stringify(payload),
161
+ });
162
+ return {
163
+ ok: res.ok,
164
+ status: res.status,
165
+ body: await this.parseBody(res),
166
+ contract: this.parseContract(res),
167
+ };
168
+ }
141
169
  async pushRuntimeSignalEvent(payload) {
142
170
  const url = `${this.config.baseUrl}/api/v1/runtime-signals/events`;
143
171
  const res = await fetch(url, {
@@ -278,6 +306,21 @@ class ConnectApiClient {
278
306
  contract: this.parseContract(res),
279
307
  };
280
308
  }
309
+ async sendRuntimeCheckin(gaid, payload, sessionId) {
310
+ const suffix = sessionId ? `/${encodeURIComponent(sessionId)}` : '';
311
+ const url = `${this.config.baseUrl}/api/v1/runtimes/${encodeURIComponent(gaid)}/checkins${suffix}`;
312
+ const res = await fetch(url, {
313
+ method: 'POST',
314
+ headers: this.getHeaders(),
315
+ body: JSON.stringify(payload),
316
+ });
317
+ return {
318
+ ok: res.ok,
319
+ status: res.status,
320
+ body: await this.parseBody(res),
321
+ contract: this.parseContract(res),
322
+ };
323
+ }
281
324
  async getProfileAccess() {
282
325
  const url = `${this.config.baseUrl}/api/profiles/access`;
283
326
  const res = await fetch(url, {
@@ -507,6 +550,20 @@ class ConnectApiClient {
507
550
  contract: this.parseContract(res),
508
551
  };
509
552
  }
553
+ async createRuntimeApiKey(gaid, label) {
554
+ const url = `${this.config.baseUrl}/api/v1/runtimes/${encodeURIComponent(gaid)}/api-keys`;
555
+ const res = await fetch(url, {
556
+ method: 'POST',
557
+ headers: this.getHeaders(),
558
+ body: JSON.stringify({ label: label ?? 'Forkit Connect runtime' }),
559
+ });
560
+ return {
561
+ ok: res.ok,
562
+ status: res.status,
563
+ body: await this.parseBody(res),
564
+ contract: this.parseContract(res),
565
+ };
566
+ }
510
567
  async parseBody(res) {
511
568
  const contentType = res.headers.get('content-type') ?? '';
512
569
  if (contentType.includes('application/json')) {
package/dist/v1/daemon.js CHANGED
@@ -10,6 +10,7 @@ exports.stopDaemonBackground = stopDaemonBackground;
10
10
  exports.restartDaemonBackground = restartDaemonBackground;
11
11
  const node_child_process_1 = require("node:child_process");
12
12
  const heartbeat_1 = require("./heartbeat");
13
+ const runtime_observation_runner_1 = require("./runtime-observation-runner");
13
14
  const DEFAULT_DAEMON_WAIT_MS = 4000;
14
15
  const DAEMON_POLL_INTERVAL_MS = 100;
15
16
  function sleep(ms) {
@@ -61,6 +62,14 @@ async function runDaemonScanCycle(service, options) {
61
62
  }
62
63
  await service.syncC2SessionsFromBackend({ suppressErrors: true });
63
64
  await service.flushC2LifecycleEvents({ suppressErrors: true });
65
+ try {
66
+ await (0, runtime_observation_runner_1.observeRegisteredRuntimeTargets)(service, {
67
+ ...(options?.agentProcessEntries ? { processEntries: options.agentProcessEntries } : {}),
68
+ });
69
+ }
70
+ catch {
71
+ // Runtime journaling is additive; daemon discovery and heartbeat must continue even if observer reads fail.
72
+ }
64
73
  service.deliverPendingNotifications(options?.notificationSender ? { notificationSender: options.notificationSender } : undefined);
65
74
  return result;
66
75
  }
@@ -0,0 +1,42 @@
1
+ export type RepoHostKind = 'github' | 'gitlab' | 'bitbucket' | 'azure-devops' | 'other';
2
+ export interface GitRemote {
3
+ name: string;
4
+ fetchUrl: string | null;
5
+ pushUrl: string | null;
6
+ }
7
+ export interface RepoDetectionResult {
8
+ cwd: string;
9
+ isGitRepo: boolean;
10
+ rootPath: string | null;
11
+ relativeCwd: string | null;
12
+ branch: string | null;
13
+ headCommit: string | null;
14
+ remotes: GitRemote[];
15
+ preferredRemote: GitRemote | null;
16
+ sourceHost: RepoHostKind | null;
17
+ repoSlug: string | null;
18
+ dirty: boolean | null;
19
+ }
20
+ export interface RepoCommandResult {
21
+ status: number | null;
22
+ stdout: string;
23
+ stderr: string;
24
+ }
25
+ export type RepoCommandRunner = (command: string, args: string[], options?: {
26
+ cwd?: string;
27
+ timeoutMs?: number;
28
+ }) => RepoCommandResult;
29
+ export declare function parseRemoteUrl(input: string): {
30
+ host: RepoHostKind;
31
+ slug: string | null;
32
+ };
33
+ export declare function classifyRepoHost(hostname: string): RepoHostKind;
34
+ export declare function parseGitRemoteOutput(output: string): GitRemote[];
35
+ export declare function parseGitStatusFiles(output: string): string[];
36
+ export declare function defaultRepoCommandRunner(command: string, args: string[], options?: {
37
+ cwd?: string;
38
+ timeoutMs?: number;
39
+ }): RepoCommandResult;
40
+ export declare function detectRepository(cwd?: string, runner?: RepoCommandRunner): RepoDetectionResult;
41
+ export declare function listRepositoryChangedFiles(cwd?: string, runner?: RepoCommandRunner): string[];
42
+ //# sourceMappingURL=repo-discovery.d.ts.map
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.parseRemoteUrl = parseRemoteUrl;
7
+ exports.classifyRepoHost = classifyRepoHost;
8
+ exports.parseGitRemoteOutput = parseGitRemoteOutput;
9
+ exports.parseGitStatusFiles = parseGitStatusFiles;
10
+ exports.defaultRepoCommandRunner = defaultRepoCommandRunner;
11
+ exports.detectRepository = detectRepository;
12
+ exports.listRepositoryChangedFiles = listRepositoryChangedFiles;
13
+ const node_child_process_1 = require("node:child_process");
14
+ const node_path_1 = __importDefault(require("node:path"));
15
+ function trimTrailingGitSuffix(value) {
16
+ return value.replace(/\.git$/i, '').replace(/\/+$/, '');
17
+ }
18
+ function normalizeRelativeRepoPath(value) {
19
+ const normalized = String(value || '').trim().replace(/\\/g, '/').replace(/^\/+/, '');
20
+ if (!normalized || normalized === '.')
21
+ return null;
22
+ return normalized;
23
+ }
24
+ function normalizeRepoPath(value) {
25
+ return trimTrailingGitSuffix(value.replace(/\\/g, '/'));
26
+ }
27
+ function parseRemoteUrl(input) {
28
+ const raw = String(input || '').trim();
29
+ if (!raw) {
30
+ return { host: 'other', slug: null };
31
+ }
32
+ const sshMatch = raw.match(/^[^@]+@([^:]+):(.+)$/);
33
+ if (sshMatch) {
34
+ const host = classifyRepoHost(sshMatch[1] || '');
35
+ return {
36
+ host,
37
+ slug: normalizeRepoPath(sshMatch[2] || '') || null,
38
+ };
39
+ }
40
+ try {
41
+ const url = new URL(raw);
42
+ const host = classifyRepoHost(url.hostname);
43
+ let pathname = normalizeRepoPath(url.pathname || '');
44
+ pathname = pathname.replace(/^\/+/, '');
45
+ if (host === 'azure-devops') {
46
+ const parts = pathname.split('/').filter(Boolean);
47
+ const devopsIndex = parts.findIndex((part) => part.toLowerCase() === '_git');
48
+ if (devopsIndex > 0 && devopsIndex < parts.length - 1) {
49
+ return {
50
+ host,
51
+ slug: `${parts.slice(0, devopsIndex).join('/')}/${parts[devopsIndex + 1]}`,
52
+ };
53
+ }
54
+ }
55
+ return {
56
+ host,
57
+ slug: pathname || null,
58
+ };
59
+ }
60
+ catch {
61
+ return {
62
+ host: 'other',
63
+ slug: null,
64
+ };
65
+ }
66
+ }
67
+ function classifyRepoHost(hostname) {
68
+ const normalized = String(hostname || '').trim().toLowerCase().replace(/^www\./, '');
69
+ if (!normalized)
70
+ return 'other';
71
+ if (normalized === 'github.com')
72
+ return 'github';
73
+ if (normalized === 'gitlab.com' || normalized.endsWith('.gitlab.com'))
74
+ return 'gitlab';
75
+ if (normalized === 'bitbucket.org' || normalized.endsWith('.bitbucket.org'))
76
+ return 'bitbucket';
77
+ if (normalized === 'dev.azure.com' || normalized.endsWith('.visualstudio.com'))
78
+ return 'azure-devops';
79
+ return 'other';
80
+ }
81
+ function parseGitRemoteOutput(output) {
82
+ const byName = new Map();
83
+ for (const rawLine of String(output || '').split(/\r?\n/)) {
84
+ const line = rawLine.trim();
85
+ if (!line)
86
+ continue;
87
+ const match = line.match(/^(\S+)\s+(\S+)\s+\((fetch|push)\)$/);
88
+ if (!match)
89
+ continue;
90
+ const name = match[1] || '';
91
+ const url = match[2] || '';
92
+ const kind = match[3] || '';
93
+ const current = byName.get(name) || {
94
+ name,
95
+ fetchUrl: null,
96
+ pushUrl: null,
97
+ };
98
+ if (kind === 'fetch')
99
+ current.fetchUrl = url;
100
+ if (kind === 'push')
101
+ current.pushUrl = url;
102
+ byName.set(name, current);
103
+ }
104
+ return [...byName.values()].sort((left, right) => left.name.localeCompare(right.name));
105
+ }
106
+ function parseGitStatusFiles(output) {
107
+ const files = [];
108
+ const seen = new Set();
109
+ for (const rawLine of String(output || '').split(/\r?\n/)) {
110
+ const line = rawLine.trimEnd();
111
+ if (!line)
112
+ continue;
113
+ const payload = line.slice(3).trim();
114
+ if (!payload)
115
+ continue;
116
+ const renamedTarget = payload.includes('->') ? payload.split('->').pop() || '' : payload;
117
+ const normalized = normalizeRelativeRepoPath(renamedTarget.trim());
118
+ if (!normalized || seen.has(normalized))
119
+ continue;
120
+ seen.add(normalized);
121
+ files.push(normalized);
122
+ }
123
+ return files;
124
+ }
125
+ function selectPreferredRemote(remotes) {
126
+ if (!remotes.length)
127
+ return null;
128
+ return remotes.find((remote) => remote.name === 'origin') || remotes[0] || null;
129
+ }
130
+ function defaultRepoCommandRunner(command, args, options) {
131
+ const result = (0, node_child_process_1.spawnSync)(command, args, {
132
+ cwd: options?.cwd,
133
+ encoding: 'utf8',
134
+ timeout: options?.timeoutMs ?? 4000,
135
+ windowsHide: true,
136
+ });
137
+ return {
138
+ status: result.status,
139
+ stdout: String(result.stdout || ''),
140
+ stderr: String(result.stderr || ''),
141
+ };
142
+ }
143
+ function runGit(cwd, args, runner) {
144
+ return runner('git', args, { cwd, timeoutMs: 4000 });
145
+ }
146
+ function detectRepository(cwd = process.cwd(), runner = defaultRepoCommandRunner) {
147
+ const normalizedCwd = node_path_1.default.resolve(cwd);
148
+ const rootResult = runGit(normalizedCwd, ['rev-parse', '--show-toplevel'], runner);
149
+ if (rootResult.status !== 0) {
150
+ return {
151
+ cwd: normalizedCwd,
152
+ isGitRepo: false,
153
+ rootPath: null,
154
+ relativeCwd: null,
155
+ branch: null,
156
+ headCommit: null,
157
+ remotes: [],
158
+ preferredRemote: null,
159
+ sourceHost: null,
160
+ repoSlug: null,
161
+ dirty: null,
162
+ };
163
+ }
164
+ const rootPath = String(rootResult.stdout || '').trim() || null;
165
+ const branchResult = rootPath
166
+ ? runGit(rootPath, ['branch', '--show-current'], runner)
167
+ : { status: 1, stdout: '', stderr: '' };
168
+ const headCommitResult = rootPath
169
+ ? runGit(rootPath, ['rev-parse', 'HEAD'], runner)
170
+ : { status: 1, stdout: '', stderr: '' };
171
+ const remoteResult = rootPath
172
+ ? runGit(rootPath, ['remote', '-v'], runner)
173
+ : { status: 1, stdout: '', stderr: '' };
174
+ const dirtyResult = rootPath
175
+ ? runGit(rootPath, ['status', '--porcelain', '--untracked-files=no'], runner)
176
+ : { status: 1, stdout: '', stderr: '' };
177
+ const remotes = parseGitRemoteOutput(remoteResult.stdout);
178
+ const preferredRemote = selectPreferredRemote(remotes);
179
+ const preferredRemoteUrl = preferredRemote?.fetchUrl || preferredRemote?.pushUrl || '';
180
+ const preferredRemoteInfo = parseRemoteUrl(preferredRemoteUrl);
181
+ return {
182
+ cwd: normalizedCwd,
183
+ isGitRepo: true,
184
+ rootPath,
185
+ relativeCwd: rootPath ? normalizeRelativeRepoPath(node_path_1.default.relative(rootPath, normalizedCwd)) : null,
186
+ branch: branchResult.status === 0 ? String(branchResult.stdout || '').trim() || null : null,
187
+ headCommit: headCommitResult.status === 0 ? String(headCommitResult.stdout || '').trim() || null : null,
188
+ remotes,
189
+ preferredRemote,
190
+ sourceHost: preferredRemote ? preferredRemoteInfo.host : null,
191
+ repoSlug: preferredRemote ? preferredRemoteInfo.slug : null,
192
+ dirty: dirtyResult.status === 0 ? String(dirtyResult.stdout || '').trim().length > 0 : null,
193
+ };
194
+ }
195
+ function listRepositoryChangedFiles(cwd = process.cwd(), runner = defaultRepoCommandRunner) {
196
+ const repo = detectRepository(cwd, runner);
197
+ if (!repo.isGitRepo || !repo.rootPath) {
198
+ return [];
199
+ }
200
+ const statusResult = runGit(repo.rootPath, ['status', '--porcelain'], runner);
201
+ if (statusResult.status !== 0) {
202
+ return [];
203
+ }
204
+ return parseGitStatusFiles(statusResult.stdout);
205
+ }
206
+ //# sourceMappingURL=repo-discovery.js.map
@@ -0,0 +1,55 @@
1
+ import type { RepoDetectionResult } from './repo-discovery';
2
+ export interface RuntimeActivityResourcesInput {
3
+ cpuPercent?: number | undefined;
4
+ memoryMb?: number | undefined;
5
+ vramMb?: number | undefined;
6
+ }
7
+ export interface RuntimeActivityThreadInput {
8
+ title: string;
9
+ taskId?: string | null;
10
+ openedAt?: string | null;
11
+ lastActiveAt?: string | null;
12
+ provider?: string | null;
13
+ actorLabel?: string | null;
14
+ workspaceHost?: string | null;
15
+ folderScope?: string | null;
16
+ }
17
+ export interface RuntimeActivityBuildInput {
18
+ cwd: string;
19
+ repo: RepoDetectionResult;
20
+ stableSubjectId?: string | undefined;
21
+ stableWorktreeId?: string | undefined;
22
+ changedFiles?: string[];
23
+ provider: string;
24
+ model: string;
25
+ serviceName: string;
26
+ serviceKind?: string | null;
27
+ status?: string | null;
28
+ startedAt: string;
29
+ endedAt?: string | null;
30
+ summary?: string | null;
31
+ clientName?: string | null;
32
+ commandLabel?: string | null;
33
+ includeServiceNameAsActor?: boolean | undefined;
34
+ actorLabels?: string[];
35
+ taskLabels?: string[];
36
+ activityThreads?: RuntimeActivityThreadInput[];
37
+ folderLabels?: string[];
38
+ fileLabels?: string[];
39
+ scopeFileLabels?: string[];
40
+ modelLabels?: string[];
41
+ promptTokens?: number | undefined;
42
+ completionTokens?: number | undefined;
43
+ cachedPromptTokens?: number | undefined;
44
+ reasoningTokens?: number | undefined;
45
+ totalTokens?: number | undefined;
46
+ latencyMs?: number | undefined;
47
+ resources?: RuntimeActivityResourcesInput;
48
+ }
49
+ export interface RuntimeActivityBuildResult {
50
+ metadata: Record<string, unknown>;
51
+ steps: Array<Record<string, unknown>>;
52
+ summary: string | null;
53
+ }
54
+ export declare function buildRuntimeActivityMetadata(input: RuntimeActivityBuildInput): RuntimeActivityBuildResult;
55
+ //# sourceMappingURL=runtime-activity.d.ts.map