@timefly/opencode-plugin 0.2.10 → 0.2.12
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/dist/cli.js +0 -0
- package/dist/event-handlers.d.ts.map +1 -1
- package/dist/event-handlers.js +1 -0
- package/dist/event-tracker.d.ts +7 -0
- package/dist/event-tracker.d.ts.map +1 -1
- package/dist/event-tracker.js +20 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -2
- package/dist/language-inference.d.ts +3 -0
- package/dist/language-inference.d.ts.map +1 -0
- package/dist/language-inference.js +75 -0
- package/dist/map-opencode-event.d.ts +3 -0
- package/dist/map-opencode-event.d.ts.map +1 -1
- package/dist/map-opencode-event.js +31 -8
- package/dist/publish-events.d.ts +2 -1
- package/dist/publish-events.d.ts.map +1 -1
- package/dist/publish-events.js +5 -3
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
File without changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-handlers.d.ts","sourceRoot":"","sources":["../src/event-handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAiBvD,OAAO,EASN,KAAK,gBAAgB,EACrB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAG/D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,SAAS,CAAC,CAAA;AAKxE,eAAO,MAAM,oBAAoB,GAChC,iBAAiB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,SAAS,UAAU,CAAC,OAAO,kBAAkB,CAAC,EAC9C,SAAS,cAAc,KACrB,OAAO,CAAC,IAAI,
|
|
1
|
+
{"version":3,"file":"event-handlers.d.ts","sourceRoot":"","sources":["../src/event-handlers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAiBvD,OAAO,EASN,KAAK,gBAAgB,EACrB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAG/D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,SAAS,CAAC,CAAA;AAKxE,eAAO,MAAM,oBAAoB,GAChC,iBAAiB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,SAAS,UAAU,CAAC,OAAO,kBAAkB,CAAC,EAC9C,SAAS,cAAc,KACrB,OAAO,CAAC,IAAI,CAgBd,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC7B,iBAAiB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,SAAS,UAAU,CAAC,OAAO,kBAAkB,CAAC,EAC9C,SAAS,cAAc,KACrB,OAAO,CAAC,IAAI,CAad,CAAA;AAED,eAAO,MAAM,oBAAoB,GAChC,iBAAiB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,SAAS,UAAU,CAAC,OAAO,kBAAkB,CAAC,EAC9C,SAAS,cAAc,KACrB,OAAO,CAAC,IAAI,CA0Dd,CAAA;AAED,eAAO,MAAM,wBAAwB,GACpC,iBAAiB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,SAAS,UAAU,CAAC,OAAO,kBAAkB,CAAC,EAC9C,SAAS,cAAc,KACrB,OAAO,CAAC,IAAI,CAqCd,CAAA;AAED,eAAO,MAAM,sBAAsB,GAClC,iBAAiB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,SAAS,UAAU,CAAC,OAAO,kBAAkB,CAAC,EAC9C,SAAS,cAAc,KACrB,OAAO,CAAC,IAAI,CAWd,CAAA;AAED,eAAO,MAAM,kBAAkB,GAC9B,iBAAiB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,SAAS,UAAU,CAAC,OAAO,kBAAkB,CAAC,EAC9C,SAAS,cAAc,KACrB,OAAO,CAAC,IAAI,CAqBd,CAAA;AAED,eAAO,MAAM,qBAAqB,GACjC,iBAAiB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACxC,SAAS,cAAc,KACrB,OAAO,CAAC,IAAI,CAad,CAAA;AAED,eAAO,MAAM,cAAc,GAC1B,OAAO,gBAAgB,EACvB,SAAS,UAAU,CAAC,OAAO,kBAAkB,CAAC,EAC9C,SAAS,cAAc,KACrB,OAAO,CAAC,IAAI,CAkCd,CAAA"}
|
package/dist/event-handlers.js
CHANGED
|
@@ -8,6 +8,7 @@ export const handleSessionCreated = (eventProperties, tracker, publish) => {
|
|
|
8
8
|
return Promise.resolve();
|
|
9
9
|
}
|
|
10
10
|
tracker.recordSessionStart(sessionInfo.id);
|
|
11
|
+
tracker.recordSessionProject(sessionInfo.id, sessionInfo.projectID, sessionInfo.directory);
|
|
11
12
|
return publish([
|
|
12
13
|
{
|
|
13
14
|
eventType: 'session_start',
|
package/dist/event-tracker.d.ts
CHANGED
|
@@ -32,6 +32,10 @@ export type SessionTiming = {
|
|
|
32
32
|
aiGenerationMs: number;
|
|
33
33
|
userWaitMs: number;
|
|
34
34
|
};
|
|
35
|
+
export type SessionProjectContext = {
|
|
36
|
+
projectId: string;
|
|
37
|
+
directory: string;
|
|
38
|
+
};
|
|
35
39
|
export type TurnTokenSnapshot = {
|
|
36
40
|
contextTokens: number;
|
|
37
41
|
cacheReadTokens: number;
|
|
@@ -49,6 +53,9 @@ export type EventTracker = {
|
|
|
49
53
|
hasProcessedPart: (partId: string) => boolean;
|
|
50
54
|
markPartProcessed: (partId: string) => void;
|
|
51
55
|
recordSessionStart: (sessionId: string, startedAtMs?: number) => void;
|
|
56
|
+
recordSessionProject: (sessionId: string, projectId: string, directory: string) => void;
|
|
57
|
+
getSessionProjectContext: (sessionId: string) => SessionProjectContext | undefined;
|
|
58
|
+
getMachineHostname: () => string;
|
|
52
59
|
recordSessionStats: (sessionId: string, delta: Partial<SessionStats>) => void;
|
|
53
60
|
recordProviderConnection: (sessionId: string, providerId: string, providerSource: string) => void;
|
|
54
61
|
recordCompactionPending: (sessionId: string, contextBeforeTokens: number) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-tracker.d.ts","sourceRoot":"","sources":["../src/event-tracker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"event-tracker.d.ts","sourceRoot":"","sources":["../src/event-tracker.ts"],"names":[],"mappings":"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"}
|
package/dist/event-tracker.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
1
2
|
const emptySessionStats = () => ({
|
|
2
3
|
billedInputTokens: 0,
|
|
3
4
|
outputTokens: 0,
|
|
@@ -52,12 +53,18 @@ const mergeSessionStats = (currentStats, delta) => ({
|
|
|
52
53
|
startedAtMs: currentStats.startedAtMs,
|
|
53
54
|
aiGenerationMs: currentStats.aiGenerationMs + (delta.aiGenerationMs ?? 0)
|
|
54
55
|
});
|
|
56
|
+
const readMachineHostname = () => {
|
|
57
|
+
const hostname = os.hostname().trim();
|
|
58
|
+
return hostname.length > 0 ? hostname : 'opencode';
|
|
59
|
+
};
|
|
55
60
|
export const createEventTracker = () => {
|
|
56
61
|
const processedMessageIds = new Set();
|
|
57
62
|
const processedUserMessageIds = new Set();
|
|
58
63
|
const processedPartIds = new Set();
|
|
59
64
|
const sessionStatsById = new Map();
|
|
65
|
+
const sessionProjectById = new Map();
|
|
60
66
|
const pendingCompactionContextBySession = new Map();
|
|
67
|
+
const machineHostname = readMachineHostname();
|
|
61
68
|
return {
|
|
62
69
|
hasProcessedMessage: (messageId) => processedMessageIds.has(messageId),
|
|
63
70
|
markMessageProcessed: (messageId) => {
|
|
@@ -81,6 +88,19 @@ export const createEventTracker = () => {
|
|
|
81
88
|
startedAtMs
|
|
82
89
|
});
|
|
83
90
|
},
|
|
91
|
+
recordSessionProject: (sessionId, projectId, directory) => {
|
|
92
|
+
const cleanProjectId = cleanIdentity(projectId);
|
|
93
|
+
const cleanDirectory = directory.trim();
|
|
94
|
+
if (!cleanProjectId && !cleanDirectory) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
sessionProjectById.set(sessionId, {
|
|
98
|
+
projectId: cleanProjectId,
|
|
99
|
+
directory: cleanDirectory
|
|
100
|
+
});
|
|
101
|
+
},
|
|
102
|
+
getSessionProjectContext: (sessionId) => sessionProjectById.get(sessionId),
|
|
103
|
+
getMachineHostname: () => machineHostname,
|
|
84
104
|
recordSessionStats: (sessionId, delta) => {
|
|
85
105
|
const currentStats = sessionStatsById.get(sessionId) ?? emptySessionStats();
|
|
86
106
|
sessionStatsById.set(sessionId, mergeSessionStats(currentStats, delta));
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAgBjD,eAAO,MAAM,qBAAqB,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAgBjD,eAAO,MAAM,qBAAqB,EAAE,MAmFnC,CAAA;AAED,eAAe,qBAAqB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ const runHookSafely = (run) => Promise.resolve()
|
|
|
10
10
|
.catch(() => undefined);
|
|
11
11
|
export const timeflyOpenCodePlugin = ({ client }) => {
|
|
12
12
|
const tracker = createEventTracker();
|
|
13
|
-
const publisher = createEventPublisher(client, PLUGIN_VERSION);
|
|
13
|
+
const publisher = createEventPublisher(client, PLUGIN_VERSION, tracker);
|
|
14
14
|
return client.app
|
|
15
15
|
.log({
|
|
16
16
|
body: {
|
|
@@ -43,8 +43,18 @@ export const timeflyOpenCodePlugin = ({ client }) => {
|
|
|
43
43
|
]);
|
|
44
44
|
}),
|
|
45
45
|
'tool.execute.before': (input) => runHookSafely(() => {
|
|
46
|
+
const toolArguments = typeof input === 'object' && input !== null && 'arguments' in input
|
|
47
|
+
? input.arguments
|
|
48
|
+
: undefined;
|
|
46
49
|
tracker.recordSessionStats(input.sessionID, { toolCallCount: 1 });
|
|
47
|
-
return publisher.publish([
|
|
50
|
+
return publisher.publish([
|
|
51
|
+
mapToolCallInput({
|
|
52
|
+
sessionID: input.sessionID,
|
|
53
|
+
tool: input.tool,
|
|
54
|
+
callID: input.callID,
|
|
55
|
+
toolArguments
|
|
56
|
+
})
|
|
57
|
+
]);
|
|
48
58
|
}),
|
|
49
59
|
'tool.execute.after': (input, output) => runHookSafely(() => {
|
|
50
60
|
tracker.recordToolOutputChars(input.sessionID, output.output.length);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"language-inference.d.ts","sourceRoot":"","sources":["../src/language-inference.ts"],"names":[],"mappings":"AA6CA,eAAO,MAAM,yBAAyB,GAAI,UAAU,MAAM,KAAG,MAgB5D,CAAA;AAQD,eAAO,MAAM,4BAA4B,GAAI,UAAU,MAAM,EAAE,WAAW,OAAO,KAAG,MA0BnF,CAAA"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const EXTENSION_LANGUAGE_MAP = {
|
|
2
|
+
cjs: 'javascript',
|
|
3
|
+
cts: 'typescript',
|
|
4
|
+
css: 'css',
|
|
5
|
+
go: 'go',
|
|
6
|
+
htm: 'html',
|
|
7
|
+
html: 'html',
|
|
8
|
+
java: 'java',
|
|
9
|
+
js: 'javascript',
|
|
10
|
+
json: 'json',
|
|
11
|
+
jsx: 'javascriptreact',
|
|
12
|
+
kt: 'kotlin',
|
|
13
|
+
kts: 'kotlin',
|
|
14
|
+
md: 'markdown',
|
|
15
|
+
mjs: 'javascript',
|
|
16
|
+
mts: 'typescript',
|
|
17
|
+
py: 'python',
|
|
18
|
+
rb: 'ruby',
|
|
19
|
+
rs: 'rust',
|
|
20
|
+
scss: 'scss',
|
|
21
|
+
sh: 'shell',
|
|
22
|
+
sql: 'sql',
|
|
23
|
+
svelte: 'svelte',
|
|
24
|
+
ts: 'typescript',
|
|
25
|
+
tsx: 'typescriptreact',
|
|
26
|
+
vue: 'vue',
|
|
27
|
+
yaml: 'yaml',
|
|
28
|
+
yml: 'yaml'
|
|
29
|
+
};
|
|
30
|
+
const FILE_PATH_TOOL_KEYS = ['path', 'file', 'file_path', 'filePath', 'target', 'uri', 'document'];
|
|
31
|
+
const isRecord = (value) => typeof value === 'object' && value !== null;
|
|
32
|
+
const cleanFilePath = (value) => {
|
|
33
|
+
const trimmedValue = value.trim();
|
|
34
|
+
if (!trimmedValue || trimmedValue === 'unknown') {
|
|
35
|
+
return '';
|
|
36
|
+
}
|
|
37
|
+
return trimmedValue.replace(/^file:\/\//i, '');
|
|
38
|
+
};
|
|
39
|
+
export const inferLanguageFromFilePath = (filePath) => {
|
|
40
|
+
const cleanedPath = cleanFilePath(filePath);
|
|
41
|
+
if (!cleanedPath) {
|
|
42
|
+
return '';
|
|
43
|
+
}
|
|
44
|
+
const normalizedPath = cleanedPath.replace(/\\/g, '/');
|
|
45
|
+
const fileName = normalizedPath.split('/').filter(Boolean).pop() || normalizedPath;
|
|
46
|
+
const extension = fileName.includes('.') ? fileName.split('.').pop()?.toLowerCase() || '' : '';
|
|
47
|
+
if (!extension) {
|
|
48
|
+
return '';
|
|
49
|
+
}
|
|
50
|
+
return EXTENSION_LANGUAGE_MAP[extension] || extension;
|
|
51
|
+
};
|
|
52
|
+
const readStringField = (record, fieldName) => {
|
|
53
|
+
const fieldValue = record[fieldName];
|
|
54
|
+
return typeof fieldValue === 'string' ? cleanFilePath(fieldValue) : '';
|
|
55
|
+
};
|
|
56
|
+
export const extractFilePathFromToolInput = (toolName, toolInput) => {
|
|
57
|
+
if (typeof toolInput === 'string') {
|
|
58
|
+
return cleanFilePath(toolInput);
|
|
59
|
+
}
|
|
60
|
+
if (!isRecord(toolInput)) {
|
|
61
|
+
return '';
|
|
62
|
+
}
|
|
63
|
+
const directPath = FILE_PATH_TOOL_KEYS.map((fieldName) => readStringField(toolInput, fieldName)).find(Boolean);
|
|
64
|
+
if (directPath) {
|
|
65
|
+
return directPath;
|
|
66
|
+
}
|
|
67
|
+
const nestedArguments = toolInput.arguments;
|
|
68
|
+
if (typeof nestedArguments === 'string') {
|
|
69
|
+
return cleanFilePath(nestedArguments);
|
|
70
|
+
}
|
|
71
|
+
if (!isRecord(nestedArguments)) {
|
|
72
|
+
return '';
|
|
73
|
+
}
|
|
74
|
+
return FILE_PATH_TOOL_KEYS.map((fieldName) => readStringField(nestedArguments, fieldName)).find(Boolean) || '';
|
|
75
|
+
};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { CreateAiUsageEventInput } from '@timefly/ai-sdk';
|
|
2
|
+
import type { EventTracker } from './event-tracker.js';
|
|
2
3
|
import type { OpenCodeAssistantMessage, OpenCodeCompactionPart, OpenCodeRetryPart, OpenCodeSessionInfo, OpenCodeStepFinishPart, OpenCodeUserMessage } from './opencode-readers.js';
|
|
3
4
|
import type { SessionStats, SessionTiming, CompactionDelta } from './event-tracker.js';
|
|
4
5
|
export type { OpenCodeAssistantMessage, OpenCodeCompactionPart, OpenCodeRetryPart, OpenCodeSessionInfo, OpenCodeStepFinishPart, OpenCodeUserMessage } from './opencode-readers.js';
|
|
5
6
|
export type { OpenCodeTokenUsage } from './token-usage.js';
|
|
6
7
|
export declare const readSessionIdOverride: (sessionId: string) => string;
|
|
7
8
|
export declare const buildModelId: (providerId: string, modelId: string) => string;
|
|
9
|
+
export declare const attachSessionContext: (tracker: Pick<EventTracker, "getSessionProjectContext" | "getMachineHostname">, input: CreateAiUsageEventInput) => CreateAiUsageEventInput;
|
|
8
10
|
export declare const mapSessionStartInput: (sessionInfo: OpenCodeSessionInfo) => Pick<CreateAiUsageEventInput, "sessionId" | "metadata">;
|
|
9
11
|
export declare const mapSessionEndInput: (sessionId: string, sessionStats: SessionStats, sessionTiming: SessionTiming) => Pick<CreateAiUsageEventInput, "sessionId" | "metadata" | "durationMs">;
|
|
10
12
|
export declare const mapLlmRequestInput: (input: {
|
|
@@ -30,6 +32,7 @@ export declare const mapToolCallInput: (input: {
|
|
|
30
32
|
sessionID: string;
|
|
31
33
|
tool: string;
|
|
32
34
|
callID: string;
|
|
35
|
+
toolArguments?: unknown;
|
|
33
36
|
}) => CreateAiUsageEventInput;
|
|
34
37
|
export declare const mapToolResultInput: (input: {
|
|
35
38
|
sessionID: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"map-opencode-event.d.ts","sourceRoot":"","sources":["../src/map-opencode-event.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iBAAiB,CAAA;AAC9D,OAAO,KAAK,EACX,wBAAwB,EACxB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,MAAM,uBAAuB,CAAA;AAE9B,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAEtF,YAAY,EACX,wBAAwB,EACxB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,mBAAmB,EACnB,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAE1D,eAAO,MAAM,qBAAqB,GAAI,WAAW,MAAM,KAAG,MAG7C,CAAA;AA8Cb,eAAO,MAAM,YAAY,GAAI,YAAY,MAAM,EAAE,SAAS,MAAM,KAAG,MAKlE,CAAA;AAED,eAAO,MAAM,oBAAoB,GAChC,aAAa,mBAAmB,KAC9B,IAAI,CAAC,uBAAuB,EAAE,WAAW,GAAG,UAAU,CAOvD,CAAA;AAEF,eAAO,MAAM,kBAAkB,GAC9B,WAAW,MAAM,EACjB,cAAc,YAAY,EAC1B,eAAe,aAAa,KAC1B,IAAI,CAAC,uBAAuB,EAAE,WAAW,GAAG,UAAU,GAAG,YAAY,CA6BtE,CAAA;AAEF,eAAO,MAAM,kBAAkB,GAAI,OAAO;IACzC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,eAAe,CAAC,EAAE,MAAM,CAAA;CACxB,KAAG,uBAiBH,CAAA;AAED,eAAO,MAAM,6BAA6B,GACzC,SAAS,wBAAwB,EACjC,UAAU;IACT,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,eAAe,CAAC,EAAE,eAAe,CAAA;CACjC,KACC,uBAAuB,GAAG,SAqC5B,CAAA;AAED,eAAO,MAAM,4BAA4B,GAAI,SAAS,wBAAwB,KAAG,uBAAuB,GAAG,SA0B1G,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,MAAM,sBAAsB,KAAG,uBAiBjE,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAI,SAAS,mBAAmB,KAAG,uBAelE,CAAA;AAED,eAAO,MAAM,kBAAkB,GAC9B,WAAW,MAAM,EACjB,sBAAsB,MAAM,EAC5B,OAAO,OAAO,KACZ,uBASD,CAAA;AAEF,eAAO,MAAM,aAAa,GACzB,WAAW,MAAM,EACjB,eAAe,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,KACtD,uBAID,CAAA;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO;IACvC,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"map-opencode-event.d.ts","sourceRoot":"","sources":["../src/map-opencode-event.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { extractFilePathFromToolInput, inferLanguageFromFilePath } from './language-inference.js';
|
|
1
2
|
import { buildTokenMetadata, buildTokenMetrics } from './token-usage.js';
|
|
2
3
|
export const readSessionIdOverride = (sessionId) => typeof process !== 'undefined' && process.env.TIMEFLY_OPENCODE_SESSION_ID
|
|
3
4
|
? process.env.TIMEFLY_OPENCODE_SESSION_ID
|
|
@@ -34,6 +35,19 @@ export const buildModelId = (providerId, modelId) => {
|
|
|
34
35
|
const cleanModelId = cleanIdentity(modelId);
|
|
35
36
|
return cleanProviderId && cleanModelId ? `${cleanProviderId}/${cleanModelId}` : cleanModelId;
|
|
36
37
|
};
|
|
38
|
+
export const attachSessionContext = (tracker, input) => {
|
|
39
|
+
const sessionContext = tracker.getSessionProjectContext(input.sessionId);
|
|
40
|
+
return {
|
|
41
|
+
...input,
|
|
42
|
+
metadata: cleanMetadata({
|
|
43
|
+
...input.metadata,
|
|
44
|
+
hostname: tracker.getMachineHostname(),
|
|
45
|
+
platform: process.platform,
|
|
46
|
+
...(sessionContext?.projectId ? { project_id: sessionContext.projectId } : {}),
|
|
47
|
+
...(sessionContext?.directory ? { directory: sessionContext.directory } : {})
|
|
48
|
+
})
|
|
49
|
+
};
|
|
50
|
+
};
|
|
37
51
|
export const mapSessionStartInput = (sessionInfo) => ({
|
|
38
52
|
sessionId: readSessionIdOverride(sessionInfo.id),
|
|
39
53
|
metadata: {
|
|
@@ -197,14 +211,23 @@ export const mapErrorInput = (sessionId, errorMetadata) => ({
|
|
|
197
211
|
eventType: 'error',
|
|
198
212
|
metadata: errorMetadata
|
|
199
213
|
});
|
|
200
|
-
export const mapToolCallInput = (input) =>
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
214
|
+
export const mapToolCallInput = (input) => {
|
|
215
|
+
const filePath = extractFilePathFromToolInput(input.tool, input.toolArguments);
|
|
216
|
+
return {
|
|
217
|
+
sessionId: readSessionIdOverride(input.sessionID),
|
|
218
|
+
eventType: 'tool_call',
|
|
219
|
+
toolName: input.tool,
|
|
220
|
+
metadata: cleanMetadata({
|
|
221
|
+
call_id: input.callID,
|
|
222
|
+
...(filePath
|
|
223
|
+
? {
|
|
224
|
+
file_path: filePath,
|
|
225
|
+
language: inferLanguageFromFilePath(filePath)
|
|
226
|
+
}
|
|
227
|
+
: {})
|
|
228
|
+
})
|
|
229
|
+
};
|
|
230
|
+
};
|
|
208
231
|
export const mapToolResultInput = (input) => ({
|
|
209
232
|
sessionId: readSessionIdOverride(input.sessionID),
|
|
210
233
|
eventType: 'tool_result',
|
package/dist/publish-events.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { type CreateAiUsageEventInput } from '@timefly/ai-sdk';
|
|
2
2
|
import type { PluginInput } from '@opencode-ai/plugin';
|
|
3
|
+
import type { EventTracker } from './event-tracker.js';
|
|
3
4
|
type EventPublisher = {
|
|
4
5
|
publish: (events: CreateAiUsageEventInput[]) => Promise<void>;
|
|
5
6
|
};
|
|
6
|
-
export declare const createEventPublisher: (client: PluginInput["client"], sourceVersion: string) => EventPublisher;
|
|
7
|
+
export declare const createEventPublisher: (client: PluginInput["client"], sourceVersion: string, tracker: Pick<EventTracker, "getSessionProjectContext" | "getMachineHostname">) => EventPublisher;
|
|
7
8
|
export {};
|
|
8
9
|
//# sourceMappingURL=publish-events.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publish-events.d.ts","sourceRoot":"","sources":["../src/publish-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4D,KAAK,uBAAuB,EAAoB,MAAM,iBAAiB,CAAA;AAC1I,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;
|
|
1
|
+
{"version":3,"file":"publish-events.d.ts","sourceRoot":"","sources":["../src/publish-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4D,KAAK,uBAAuB,EAAoB,MAAM,iBAAiB,CAAA;AAC1I,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAKtD,KAAK,cAAc,GAAG;IACrB,OAAO,EAAE,CAAC,MAAM,EAAE,uBAAuB,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7D,CAAA;AA+BD,eAAO,MAAM,oBAAoB,GAChC,QAAQ,WAAW,CAAC,QAAQ,CAAC,EAC7B,eAAe,MAAM,EACrB,SAAS,IAAI,CAAC,YAAY,EAAE,0BAA0B,GAAG,oBAAoB,CAAC,KAC5E,cAsBF,CAAA"}
|
package/dist/publish-events.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createAiUsageEvent, createTimeFlyAiClient, isSyncFailure } from '@timefly/ai-sdk';
|
|
2
|
+
import { attachSessionContext } from './map-opencode-event.js';
|
|
2
3
|
const PRICING_URL = 'https://timefly.dev/pricing';
|
|
3
4
|
const buildSyncFailureMessage = (error) => {
|
|
4
5
|
if (error.isSupporterRequired) {
|
|
@@ -24,8 +25,7 @@ const logPublishFailure = (client, error) => {
|
|
|
24
25
|
.then(() => undefined)
|
|
25
26
|
.catch(() => undefined);
|
|
26
27
|
};
|
|
27
|
-
const
|
|
28
|
-
export const createEventPublisher = (client, sourceVersion) => {
|
|
28
|
+
export const createEventPublisher = (client, sourceVersion, tracker) => {
|
|
29
29
|
const timeflyClient = createTimeFlyAiClient({
|
|
30
30
|
source: 'opencode',
|
|
31
31
|
sourceVersion
|
|
@@ -35,7 +35,9 @@ export const createEventPublisher = (client, sourceVersion) => {
|
|
|
35
35
|
if (!events.length) {
|
|
36
36
|
return Promise.resolve();
|
|
37
37
|
}
|
|
38
|
-
const usageEvents =
|
|
38
|
+
const usageEvents = events
|
|
39
|
+
.map((eventInput) => attachSessionContext(tracker, eventInput))
|
|
40
|
+
.map((eventInput) => createAiUsageEvent('opencode', sourceVersion, eventInput));
|
|
39
41
|
return timeflyClient
|
|
40
42
|
.recordEvents(usageEvents)
|
|
41
43
|
.then(() => undefined)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timefly/opencode-plugin",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.12",
|
|
4
4
|
"description": "TimeFly telemetry plugin for OpenCode — sessions, tokens, models, and tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": "./dist/cli.js",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@opencode-ai/plugin": "^1.17.7",
|
|
60
|
-
"@timefly/ai-sdk": "
|
|
60
|
+
"@timefly/ai-sdk": "0.2.3",
|
|
61
61
|
"@types/bun": "^1.3.14",
|
|
62
62
|
"@types/node": "^22.15.21",
|
|
63
63
|
"typescript": "^5.9.3"
|