@clinebot/core 0.0.4 → 0.0.6
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/agents/agent-config-parser.d.ts +1 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.node.d.ts +1 -0
- package/dist/index.node.js +134 -107
- package/dist/runtime/session-runtime.d.ts +4 -2
- package/dist/session/default-session-manager.d.ts +5 -1
- package/dist/session/session-host.d.ts +3 -1
- package/dist/session/session-manager.d.ts +2 -1
- package/dist/session/unified-session-persistence-service.d.ts +4 -0
- package/dist/telemetry/ITelemetryAdapter.d.ts +54 -0
- package/dist/telemetry/LoggerTelemetryAdapter.d.ts +21 -0
- package/dist/telemetry/OpenTelemetryAdapter.d.ts +43 -0
- package/dist/telemetry/OpenTelemetryProvider.d.ts +41 -0
- package/dist/telemetry/TelemetryService.d.ts +34 -0
- package/dist/telemetry/opentelemetry.d.ts +3 -0
- package/dist/telemetry/opentelemetry.js +27 -0
- package/dist/{default-tools → tools}/schemas.d.ts +6 -0
- package/dist/types/config.d.ts +3 -2
- package/package.json +17 -3
- package/src/agents/agent-config-parser.ts +1 -1
- package/src/agents/hooks-config-loader.ts +19 -1
- package/src/index.node.ts +3 -0
- package/src/index.ts +35 -19
- package/src/providers/local-provider-service.ts +25 -7
- package/src/runtime/hook-file-hooks.test.ts +47 -0
- package/src/runtime/hook-file-hooks.ts +3 -0
- package/src/runtime/runtime-builder.test.ts +20 -0
- package/src/runtime/runtime-builder.ts +3 -2
- package/src/runtime/runtime-parity.test.ts +1 -1
- package/src/runtime/session-runtime.ts +4 -2
- package/src/session/default-session-manager.test.ts +72 -0
- package/src/session/default-session-manager.ts +63 -6
- package/src/session/session-host.ts +7 -2
- package/src/session/session-manager.ts +2 -1
- package/src/session/unified-session-persistence-service.ts +213 -23
- package/src/telemetry/ITelemetryAdapter.ts +94 -0
- package/src/telemetry/LoggerTelemetryAdapter.test.ts +42 -0
- package/src/telemetry/LoggerTelemetryAdapter.ts +114 -0
- package/src/telemetry/OpenTelemetryAdapter.test.ts +157 -0
- package/src/telemetry/OpenTelemetryAdapter.ts +348 -0
- package/src/telemetry/OpenTelemetryProvider.test.ts +113 -0
- package/src/telemetry/OpenTelemetryProvider.ts +322 -0
- package/src/telemetry/TelemetryService.test.ts +134 -0
- package/src/telemetry/TelemetryService.ts +141 -0
- package/src/telemetry/opentelemetry.ts +20 -0
- package/src/{default-tools → tools}/definitions.ts +35 -28
- package/src/{default-tools → tools}/schemas.ts +9 -0
- package/src/types/config.ts +3 -1
- /package/dist/{default-tools → tools}/constants.d.ts +0 -0
- /package/dist/{default-tools → tools}/definitions.d.ts +0 -0
- /package/dist/{default-tools → tools}/executors/apply-patch-parser.d.ts +0 -0
- /package/dist/{default-tools → tools}/executors/apply-patch.d.ts +0 -0
- /package/dist/{default-tools → tools}/executors/bash.d.ts +0 -0
- /package/dist/{default-tools → tools}/executors/editor.d.ts +0 -0
- /package/dist/{default-tools → tools}/executors/file-read.d.ts +0 -0
- /package/dist/{default-tools → tools}/executors/index.d.ts +0 -0
- /package/dist/{default-tools → tools}/executors/search.d.ts +0 -0
- /package/dist/{default-tools → tools}/executors/web-fetch.d.ts +0 -0
- /package/dist/{default-tools → tools}/index.d.ts +0 -0
- /package/dist/{default-tools → tools}/model-tool-routing.d.ts +0 -0
- /package/dist/{default-tools → tools}/presets.d.ts +0 -0
- /package/dist/{default-tools → tools}/types.d.ts +0 -0
- /package/src/{default-tools → tools}/constants.ts +0 -0
- /package/src/{default-tools → tools}/definitions.test.ts +0 -0
- /package/src/{default-tools → tools}/executors/apply-patch-parser.ts +0 -0
- /package/src/{default-tools → tools}/executors/apply-patch.ts +0 -0
- /package/src/{default-tools → tools}/executors/bash.ts +0 -0
- /package/src/{default-tools → tools}/executors/editor.ts +0 -0
- /package/src/{default-tools → tools}/executors/file-read.test.ts +0 -0
- /package/src/{default-tools → tools}/executors/file-read.ts +0 -0
- /package/src/{default-tools → tools}/executors/index.ts +0 -0
- /package/src/{default-tools → tools}/executors/search.ts +0 -0
- /package/src/{default-tools → tools}/executors/web-fetch.ts +0 -0
- /package/src/{default-tools → tools}/index.ts +0 -0
- /package/src/{default-tools → tools}/model-tool-routing.test.ts +0 -0
- /package/src/{default-tools → tools}/model-tool-routing.ts +0 -0
- /package/src/{default-tools → tools}/presets.test.ts +0 -0
- /package/src/{default-tools → tools}/presets.ts +0 -0
- /package/src/{default-tools → tools}/types.ts +0 -0
|
@@ -23,6 +23,12 @@ export declare const ReadFilesInputUnionSchema: z.ZodUnion<readonly [z.ZodObject
|
|
|
23
23
|
export declare const SearchCodebaseInputSchema: z.ZodObject<{
|
|
24
24
|
queries: z.ZodArray<z.ZodString>;
|
|
25
25
|
}, z.core.$strip>;
|
|
26
|
+
/**
|
|
27
|
+
* Union schema for search_codebase tool input, allowing either a single string, an array of strings, or the full object schema
|
|
28
|
+
*/
|
|
29
|
+
export declare const SearchCodebaseUnionInputSchema: z.ZodUnion<readonly [z.ZodObject<{
|
|
30
|
+
queries: z.ZodArray<z.ZodString>;
|
|
31
|
+
}, z.core.$strip>, z.ZodArray<z.ZodString>, z.ZodString]>;
|
|
26
32
|
/**
|
|
27
33
|
* Schema for run_commands tool input
|
|
28
34
|
*/
|
package/dist/types/config.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AgentConfig, AgentHooks, ConsecutiveMistakeLimitContext, ConsecutiveMistakeLimitDecision, HookErrorMode, TeamEvent, Tool } from "@clinebot/agents";
|
|
2
2
|
import type { providers as LlmsProviders } from "@clinebot/llms";
|
|
3
|
-
import type { AgentMode, BasicLogger, SessionExecutionConfig, SessionPromptConfig, SessionWorkspaceConfig } from "@clinebot/shared";
|
|
4
|
-
import type { ToolRoutingRule } from "../
|
|
3
|
+
import type { AgentMode, BasicLogger, ITelemetryService, SessionExecutionConfig, SessionPromptConfig, SessionWorkspaceConfig } from "@clinebot/shared";
|
|
4
|
+
import type { ToolRoutingRule } from "../tools/model-tool-routing.js";
|
|
5
5
|
export type CoreAgentMode = AgentMode;
|
|
6
6
|
export interface CoreModelConfig {
|
|
7
7
|
providerId: string;
|
|
@@ -35,6 +35,7 @@ export interface CoreSessionConfig extends CoreModelConfig, CoreRuntimeFeatures,
|
|
|
35
35
|
hooks?: AgentHooks;
|
|
36
36
|
hookErrorMode?: HookErrorMode;
|
|
37
37
|
logger?: BasicLogger;
|
|
38
|
+
telemetry?: ITelemetryService;
|
|
38
39
|
extraTools?: Tool[];
|
|
39
40
|
pluginPaths?: string[];
|
|
40
41
|
extensions?: AgentConfig["extensions"];
|
package/package.json
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clinebot/core",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"main": "./dist/index.node.js",
|
|
5
5
|
"dependencies": {
|
|
6
|
-
"@clinebot/agents": "0.0.
|
|
7
|
-
"@clinebot/llms": "0.0.
|
|
6
|
+
"@clinebot/agents": "0.0.6",
|
|
7
|
+
"@clinebot/llms": "0.0.6",
|
|
8
|
+
"@opentelemetry/api": "^1.9.0",
|
|
9
|
+
"@opentelemetry/api-logs": "^0.56.0",
|
|
10
|
+
"@opentelemetry/exporter-logs-otlp-http": "^0.56.0",
|
|
11
|
+
"@opentelemetry/exporter-metrics-otlp-http": "^0.56.0",
|
|
12
|
+
"@opentelemetry/resources": "^1.30.1",
|
|
13
|
+
"@opentelemetry/sdk-logs": "^0.56.0",
|
|
14
|
+
"@opentelemetry/sdk-metrics": "^1.30.1",
|
|
15
|
+
"@opentelemetry/semantic-conventions": "^1.37.0",
|
|
16
|
+
"better-sqlite3": "^11.10.0",
|
|
8
17
|
"nanoid": "^5.1.7",
|
|
9
18
|
"simple-git": "^3.32.3",
|
|
10
19
|
"yaml": "^2.8.2",
|
|
@@ -20,6 +29,11 @@
|
|
|
20
29
|
"development": "./src/index.node.ts",
|
|
21
30
|
"types": "./dist/index.node.d.ts",
|
|
22
31
|
"import": "./dist/index.node.js"
|
|
32
|
+
},
|
|
33
|
+
"./telemetry/opentelemetry": {
|
|
34
|
+
"development": "./src/telemetry/opentelemetry.ts",
|
|
35
|
+
"types": "./dist/telemetry/opentelemetry.d.ts",
|
|
36
|
+
"import": "./dist/telemetry/opentelemetry.js"
|
|
23
37
|
}
|
|
24
38
|
},
|
|
25
39
|
"description": "State-aware orchestration for Cline Agent runtimes",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AgentConfig, Tool } from "@clinebot/agents";
|
|
2
2
|
import YAML from "yaml";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import { ALL_DEFAULT_TOOL_NAMES, type DefaultToolName } from "../
|
|
4
|
+
import { ALL_DEFAULT_TOOL_NAMES, type DefaultToolName } from "../tools";
|
|
5
5
|
|
|
6
6
|
const AgentConfigFrontmatterSchema = z.object({
|
|
7
7
|
name: z.string().trim().min(1),
|
|
@@ -45,10 +45,28 @@ const HOOK_CONFIG_FILE_LOOKUP = new Map<string, HookConfigFileName>(
|
|
|
45
45
|
Object.values(HookConfigFileName).map((name) => [name.toLowerCase(), name]),
|
|
46
46
|
);
|
|
47
47
|
|
|
48
|
+
const SUPPORTED_HOOK_FILE_EXTENSIONS = new Set([
|
|
49
|
+
"",
|
|
50
|
+
".sh",
|
|
51
|
+
".bash",
|
|
52
|
+
".zsh",
|
|
53
|
+
".js",
|
|
54
|
+
".mjs",
|
|
55
|
+
".cjs",
|
|
56
|
+
".ts",
|
|
57
|
+
".mts",
|
|
58
|
+
".cts",
|
|
59
|
+
".py",
|
|
60
|
+
]);
|
|
61
|
+
|
|
48
62
|
export function toHookConfigFileName(
|
|
49
63
|
fileName: string,
|
|
50
64
|
): HookConfigFileName | undefined {
|
|
51
|
-
const
|
|
65
|
+
const extension = extname(fileName).toLowerCase();
|
|
66
|
+
if (!SUPPORTED_HOOK_FILE_EXTENSIONS.has(extension)) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
const key = basename(fileName, extension).trim().toLowerCase();
|
|
52
70
|
return HOOK_CONFIG_FILE_LOOKUP.get(key);
|
|
53
71
|
}
|
|
54
72
|
|
package/src/index.node.ts
CHANGED
|
@@ -100,6 +100,9 @@ export {
|
|
|
100
100
|
OCI_HEADER_OPC_REQUEST_ID,
|
|
101
101
|
refreshOcaToken,
|
|
102
102
|
} from "./auth/oca";
|
|
103
|
+
export async function loadOpenTelemetryAdapter() {
|
|
104
|
+
return import("./telemetry/opentelemetry.js");
|
|
105
|
+
}
|
|
103
106
|
export { startLocalOAuthServer } from "./auth/server";
|
|
104
107
|
export type {
|
|
105
108
|
OAuthCredentials,
|
package/src/index.ts
CHANGED
|
@@ -19,6 +19,7 @@ export type {
|
|
|
19
19
|
BasicLogger,
|
|
20
20
|
ConnectorHookEvent,
|
|
21
21
|
HookSessionContext,
|
|
22
|
+
ITelemetryService,
|
|
22
23
|
RpcAddProviderActionRequest,
|
|
23
24
|
RpcChatMessage,
|
|
24
25
|
RpcChatRunTurnRequest,
|
|
@@ -38,6 +39,12 @@ export type {
|
|
|
38
39
|
RpcSaveProviderSettingsActionRequest,
|
|
39
40
|
SessionLineage,
|
|
40
41
|
TeamProgressProjectionEvent,
|
|
42
|
+
TelemetryArray,
|
|
43
|
+
TelemetryMetadata,
|
|
44
|
+
TelemetryObject,
|
|
45
|
+
TelemetryPrimitive,
|
|
46
|
+
TelemetryProperties,
|
|
47
|
+
TelemetryValue,
|
|
41
48
|
ToolPolicy,
|
|
42
49
|
} from "@clinebot/shared";
|
|
43
50
|
export {
|
|
@@ -85,25 +92,6 @@ export {
|
|
|
85
92
|
ChatSummarySchema,
|
|
86
93
|
ChatViewStateSchema,
|
|
87
94
|
} from "./chat/chat-schema";
|
|
88
|
-
export {
|
|
89
|
-
ALL_DEFAULT_TOOL_NAMES,
|
|
90
|
-
type AskQuestionExecutor,
|
|
91
|
-
type CreateBuiltinToolsOptions,
|
|
92
|
-
type CreateDefaultToolsOptions,
|
|
93
|
-
createBuiltinTools,
|
|
94
|
-
createDefaultExecutors,
|
|
95
|
-
createDefaultTools,
|
|
96
|
-
createDefaultToolsWithPreset,
|
|
97
|
-
createToolPoliciesWithPreset,
|
|
98
|
-
type DefaultExecutorsOptions,
|
|
99
|
-
type DefaultToolName,
|
|
100
|
-
DefaultToolNames,
|
|
101
|
-
type DefaultToolsConfig,
|
|
102
|
-
type ToolExecutors,
|
|
103
|
-
type ToolPolicyPresetName,
|
|
104
|
-
type ToolPresetName,
|
|
105
|
-
ToolPresets,
|
|
106
|
-
} from "./default-tools";
|
|
107
95
|
export {
|
|
108
96
|
hasMcpSettingsFile,
|
|
109
97
|
InMemoryMcpManager,
|
|
@@ -135,6 +123,34 @@ export {
|
|
|
135
123
|
buildTeamProgressSummary,
|
|
136
124
|
toTeamProgressLifecycleEvent,
|
|
137
125
|
} from "./team";
|
|
126
|
+
export type { ITelemetryAdapter } from "./telemetry/ITelemetryAdapter";
|
|
127
|
+
export {
|
|
128
|
+
LoggerTelemetryAdapter,
|
|
129
|
+
type LoggerTelemetryAdapterOptions,
|
|
130
|
+
} from "./telemetry/LoggerTelemetryAdapter";
|
|
131
|
+
export {
|
|
132
|
+
TelemetryService,
|
|
133
|
+
type TelemetryServiceOptions,
|
|
134
|
+
} from "./telemetry/TelemetryService";
|
|
135
|
+
export {
|
|
136
|
+
ALL_DEFAULT_TOOL_NAMES,
|
|
137
|
+
type AskQuestionExecutor,
|
|
138
|
+
type CreateBuiltinToolsOptions,
|
|
139
|
+
type CreateDefaultToolsOptions,
|
|
140
|
+
createBuiltinTools,
|
|
141
|
+
createDefaultExecutors,
|
|
142
|
+
createDefaultTools,
|
|
143
|
+
createDefaultToolsWithPreset,
|
|
144
|
+
createToolPoliciesWithPreset,
|
|
145
|
+
type DefaultExecutorsOptions,
|
|
146
|
+
type DefaultToolName,
|
|
147
|
+
DefaultToolNames,
|
|
148
|
+
type DefaultToolsConfig,
|
|
149
|
+
type ToolExecutors,
|
|
150
|
+
type ToolPolicyPresetName,
|
|
151
|
+
type ToolPresetName,
|
|
152
|
+
ToolPresets,
|
|
153
|
+
} from "./tools";
|
|
138
154
|
// Compatibility barrel (legacy imports).
|
|
139
155
|
export type { RuntimeEnvironment, SessionEvent, StoredMessages } from "./types";
|
|
140
156
|
export type { SessionStatus } from "./types/common";
|
|
@@ -35,6 +35,7 @@ type StoredModelsFile = {
|
|
|
35
35
|
name: string;
|
|
36
36
|
supportsVision?: boolean;
|
|
37
37
|
supportsAttachments?: boolean;
|
|
38
|
+
supportsReasoning?: boolean;
|
|
38
39
|
}
|
|
39
40
|
>;
|
|
40
41
|
}
|
|
@@ -132,6 +133,24 @@ async function writeModelsFile(
|
|
|
132
133
|
await writeFile(filePath, `${JSON.stringify(state, null, 2)}\n`, "utf8");
|
|
133
134
|
}
|
|
134
135
|
|
|
136
|
+
function toRpcProviderModel(
|
|
137
|
+
modelId: string,
|
|
138
|
+
info: {
|
|
139
|
+
name?: string;
|
|
140
|
+
capabilities?: string[];
|
|
141
|
+
thinkingConfig?: unknown;
|
|
142
|
+
},
|
|
143
|
+
): RpcProviderModel {
|
|
144
|
+
return {
|
|
145
|
+
id: modelId,
|
|
146
|
+
name: info.name ?? modelId,
|
|
147
|
+
supportsAttachments: info.capabilities?.includes("files"),
|
|
148
|
+
supportsVision: info.capabilities?.includes("images"),
|
|
149
|
+
supportsReasoning:
|
|
150
|
+
info.capabilities?.includes("reasoning") || info.thinkingConfig != null,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
135
154
|
function toProviderCapabilities(
|
|
136
155
|
capabilities: RpcProviderCapability[] | undefined,
|
|
137
156
|
): Array<"reasoning" | "prompt-cache" | "tools"> | undefined {
|
|
@@ -352,6 +371,7 @@ export async function addLocalProvider(
|
|
|
352
371
|
const modelsState = await readModelsFile(modelsPath);
|
|
353
372
|
const supportsVision = capabilities?.includes("vision") ?? false;
|
|
354
373
|
const supportsAttachments = supportsVision;
|
|
374
|
+
const supportsReasoning = capabilities?.includes("reasoning") ?? false;
|
|
355
375
|
modelsState.providers[providerId] = {
|
|
356
376
|
provider: {
|
|
357
377
|
name: providerName,
|
|
@@ -368,6 +388,7 @@ export async function addLocalProvider(
|
|
|
368
388
|
name: modelId,
|
|
369
389
|
supportsVision,
|
|
370
390
|
supportsAttachments,
|
|
391
|
+
supportsReasoning,
|
|
371
392
|
},
|
|
372
393
|
]),
|
|
373
394
|
),
|
|
@@ -394,12 +415,13 @@ export async function listLocalProviders(
|
|
|
394
415
|
const providerItems = await Promise.all(
|
|
395
416
|
ids.map(async (id): Promise<RpcProviderListItem> => {
|
|
396
417
|
const info = await models.getProvider(id);
|
|
418
|
+
const providerModels = await getLocalProviderModels(id);
|
|
397
419
|
const persistedSettings = state.providers[id]?.settings;
|
|
398
420
|
const providerName = info?.name ?? titleCaseFromId(id);
|
|
399
421
|
return {
|
|
400
422
|
id,
|
|
401
423
|
name: providerName,
|
|
402
|
-
models:
|
|
424
|
+
models: providerModels.models.length,
|
|
403
425
|
color: stableColor(id),
|
|
404
426
|
letter: createLetter(providerName),
|
|
405
427
|
enabled: Boolean(persistedSettings),
|
|
@@ -413,6 +435,7 @@ export async function listLocalProviders(
|
|
|
413
435
|
defaultModelId: info?.defaultModelId,
|
|
414
436
|
authDescription: "This provider uses API keys for authentication.",
|
|
415
437
|
baseUrlDescription: "The base endpoint to use for provider requests.",
|
|
438
|
+
modelList: providerModels.models,
|
|
416
439
|
};
|
|
417
440
|
}),
|
|
418
441
|
);
|
|
@@ -430,12 +453,7 @@ export async function getLocalProviderModels(
|
|
|
430
453
|
const modelMap = await models.getModelsForProvider(id);
|
|
431
454
|
const items = Object.entries(modelMap)
|
|
432
455
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
433
|
-
.map(([modelId, info]) => (
|
|
434
|
-
id: modelId,
|
|
435
|
-
name: info.name ?? modelId,
|
|
436
|
-
supportsAttachments: info.capabilities?.includes("files"),
|
|
437
|
-
supportsVision: info.capabilities?.includes("images"),
|
|
438
|
-
}));
|
|
456
|
+
.map(([modelId, info]) => toRpcProviderModel(modelId, info));
|
|
439
457
|
return {
|
|
440
458
|
providerId: id,
|
|
441
459
|
models: items,
|
|
@@ -17,6 +17,22 @@ async function createWorkspaceWithHook(
|
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
describe("createHookConfigFileHooks", () => {
|
|
20
|
+
it("ignores example hook files", async () => {
|
|
21
|
+
const { workspace } = await createWorkspaceWithHook(
|
|
22
|
+
"PreToolUse.example",
|
|
23
|
+
'echo \'HOOK_CONTROL\t{"cancel":true,"context":"should-not-run"}\'\n',
|
|
24
|
+
);
|
|
25
|
+
try {
|
|
26
|
+
const hooks = createHookConfigFileHooks({
|
|
27
|
+
cwd: workspace,
|
|
28
|
+
workspacePath: workspace,
|
|
29
|
+
});
|
|
30
|
+
expect(hooks).toBeUndefined();
|
|
31
|
+
} finally {
|
|
32
|
+
await rm(workspace, { recursive: true, force: true });
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
|
|
20
36
|
it("executes extensionless legacy hook files via bash fallback", async () => {
|
|
21
37
|
const { workspace } = await createWorkspaceWithHook(
|
|
22
38
|
"PreToolUse",
|
|
@@ -103,4 +119,35 @@ describe("createHookConfigFileHooks", () => {
|
|
|
103
119
|
await rm(workspace, { recursive: true, force: true });
|
|
104
120
|
}
|
|
105
121
|
});
|
|
122
|
+
|
|
123
|
+
it("executes python hook files", async () => {
|
|
124
|
+
const { workspace } = await createWorkspaceWithHook(
|
|
125
|
+
"PreToolUse.py",
|
|
126
|
+
'print(\'HOOK_CONTROL\\t{"cancel": false, "context": "python-ok"}\')\n',
|
|
127
|
+
);
|
|
128
|
+
try {
|
|
129
|
+
const hooks = createHookConfigFileHooks({
|
|
130
|
+
cwd: workspace,
|
|
131
|
+
workspacePath: workspace,
|
|
132
|
+
});
|
|
133
|
+
expect(hooks?.onToolCallStart).toBeTypeOf("function");
|
|
134
|
+
const control = await hooks?.onToolCallStart?.({
|
|
135
|
+
agentId: "agent_1",
|
|
136
|
+
conversationId: "conv_1",
|
|
137
|
+
parentAgentId: null,
|
|
138
|
+
iteration: 1,
|
|
139
|
+
call: {
|
|
140
|
+
id: "call_1",
|
|
141
|
+
name: "read_file",
|
|
142
|
+
input: { path: "README.md" },
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
expect(control).toMatchObject({
|
|
146
|
+
cancel: false,
|
|
147
|
+
context: "python-ok",
|
|
148
|
+
});
|
|
149
|
+
} finally {
|
|
150
|
+
await rm(workspace, { recursive: true, force: true });
|
|
151
|
+
}
|
|
152
|
+
});
|
|
106
153
|
});
|
|
@@ -323,6 +323,9 @@ function inferHookCommand(path: string): string[] {
|
|
|
323
323
|
) {
|
|
324
324
|
return ["bun", "run", path];
|
|
325
325
|
}
|
|
326
|
+
if (lowered.endsWith(".py")) {
|
|
327
|
+
return ["python3", path];
|
|
328
|
+
}
|
|
326
329
|
// Default to bash for legacy hook files with no extension/shebang.
|
|
327
330
|
return ["/bin/bash", path];
|
|
328
331
|
}
|
|
@@ -3,6 +3,7 @@ import { tmpdir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import type { Tool } from "@clinebot/agents";
|
|
5
5
|
import { describe, expect, it } from "vitest";
|
|
6
|
+
import { TelemetryService } from "../telemetry/TelemetryService";
|
|
6
7
|
import { DefaultRuntimeBuilder } from "./runtime-builder";
|
|
7
8
|
|
|
8
9
|
function makeSpawnTool(): Tool {
|
|
@@ -55,6 +56,25 @@ describe("DefaultRuntimeBuilder", () => {
|
|
|
55
56
|
expect(runtime.logger).toBe(logger);
|
|
56
57
|
});
|
|
57
58
|
|
|
59
|
+
it("forwards telemetry for downstream runtime consumers", () => {
|
|
60
|
+
const telemetry = new TelemetryService();
|
|
61
|
+
const runtime = new DefaultRuntimeBuilder().build({
|
|
62
|
+
config: {
|
|
63
|
+
providerId: "anthropic",
|
|
64
|
+
modelId: "claude-sonnet-4-6",
|
|
65
|
+
apiKey: "key",
|
|
66
|
+
systemPrompt: "test",
|
|
67
|
+
cwd: process.cwd(),
|
|
68
|
+
enableTools: false,
|
|
69
|
+
enableSpawnAgent: false,
|
|
70
|
+
enableAgentTeams: false,
|
|
71
|
+
telemetry,
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
expect(runtime.telemetry).toBe(telemetry);
|
|
76
|
+
});
|
|
77
|
+
|
|
58
78
|
it("uses readonly preset in plan mode", () => {
|
|
59
79
|
const runtime = new DefaultRuntimeBuilder().build({
|
|
60
80
|
config: {
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
type SkillConfig,
|
|
15
15
|
type UserInstructionConfigWatcher,
|
|
16
16
|
} from "../agents";
|
|
17
|
+
import { SqliteTeamStore } from "../storage/sqlite-team-store";
|
|
17
18
|
import {
|
|
18
19
|
createBuiltinTools,
|
|
19
20
|
DEFAULT_MODEL_TOOL_ROUTING_RULES,
|
|
@@ -22,8 +23,7 @@ import {
|
|
|
22
23
|
type ToolExecutors,
|
|
23
24
|
ToolPresets,
|
|
24
25
|
type ToolRoutingRule,
|
|
25
|
-
} from "../
|
|
26
|
-
import { SqliteTeamStore } from "../storage/sqlite-team-store";
|
|
26
|
+
} from "../tools";
|
|
27
27
|
import type { CoreAgentMode, CoreSessionConfig } from "../types/config";
|
|
28
28
|
import type {
|
|
29
29
|
RuntimeBuilder,
|
|
@@ -522,6 +522,7 @@ export class DefaultRuntimeBuilder implements RuntimeBuilder {
|
|
|
522
522
|
return {
|
|
523
523
|
tools,
|
|
524
524
|
logger: logger ?? config.logger,
|
|
525
|
+
telemetry: input.telemetry ?? config.telemetry,
|
|
525
526
|
teamRuntime,
|
|
526
527
|
completionGuard,
|
|
527
528
|
shutdown: (reason: string) => {
|
|
@@ -3,7 +3,7 @@ import { tmpdir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import type { Tool } from "@clinebot/agents";
|
|
5
5
|
import { describe, expect, it } from "vitest";
|
|
6
|
-
import { createBuiltinTools } from "../
|
|
6
|
+
import { createBuiltinTools } from "../tools";
|
|
7
7
|
import { DefaultRuntimeBuilder } from "./runtime-builder";
|
|
8
8
|
|
|
9
9
|
type LegacyConfig = {
|
|
@@ -5,15 +5,16 @@ import type {
|
|
|
5
5
|
AgentTeamsRuntime,
|
|
6
6
|
Tool,
|
|
7
7
|
} from "@clinebot/agents";
|
|
8
|
-
import type { BasicLogger } from "@clinebot/shared";
|
|
8
|
+
import type { BasicLogger, ITelemetryService } from "@clinebot/shared";
|
|
9
9
|
import type { UserInstructionConfigWatcher } from "../agents";
|
|
10
|
-
import type { ToolExecutors } from "../
|
|
10
|
+
import type { ToolExecutors } from "../tools";
|
|
11
11
|
import type { CoreSessionConfig } from "../types/config";
|
|
12
12
|
|
|
13
13
|
export interface BuiltRuntime {
|
|
14
14
|
tools: Tool[];
|
|
15
15
|
hooks?: AgentHooks;
|
|
16
16
|
logger?: BasicLogger;
|
|
17
|
+
telemetry?: ITelemetryService;
|
|
17
18
|
teamRuntime?: AgentTeamsRuntime;
|
|
18
19
|
completionGuard?: () => string | undefined;
|
|
19
20
|
shutdown: (reason: string) => Promise<void> | void;
|
|
@@ -29,6 +30,7 @@ export interface RuntimeBuilderInput {
|
|
|
29
30
|
userInstructionWatcher?: UserInstructionConfigWatcher;
|
|
30
31
|
defaultToolExecutors?: Partial<ToolExecutors>;
|
|
31
32
|
logger?: BasicLogger;
|
|
33
|
+
telemetry?: ITelemetryService;
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
export interface RuntimeBuilder {
|
|
@@ -3,6 +3,7 @@ import { tmpdir } from "node:os";
|
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import type { AgentResult } from "@clinebot/agents";
|
|
5
5
|
import { describe, expect, it, vi } from "vitest";
|
|
6
|
+
import { TelemetryService } from "../telemetry/TelemetryService";
|
|
6
7
|
import { SessionSource } from "../types/common";
|
|
7
8
|
import type { CoreSessionConfig } from "../types/config";
|
|
8
9
|
import { DefaultSessionManager } from "./default-session-manager";
|
|
@@ -70,6 +71,77 @@ function createConfig(
|
|
|
70
71
|
}
|
|
71
72
|
|
|
72
73
|
describe("DefaultSessionManager", () => {
|
|
74
|
+
it("emits session lifecycle telemetry when configured", async () => {
|
|
75
|
+
const sessionId = "sess-telemetry";
|
|
76
|
+
const manifest = createManifest(sessionId);
|
|
77
|
+
const adapter = {
|
|
78
|
+
name: "test",
|
|
79
|
+
emit: vi.fn(),
|
|
80
|
+
emitRequired: vi.fn(),
|
|
81
|
+
recordCounter: vi.fn(),
|
|
82
|
+
recordHistogram: vi.fn(),
|
|
83
|
+
recordGauge: vi.fn(),
|
|
84
|
+
isEnabled: vi.fn(() => true),
|
|
85
|
+
flush: vi.fn().mockResolvedValue(undefined),
|
|
86
|
+
dispose: vi.fn().mockResolvedValue(undefined),
|
|
87
|
+
};
|
|
88
|
+
const telemetry = new TelemetryService({
|
|
89
|
+
adapters: [adapter],
|
|
90
|
+
distinctId: distinctId,
|
|
91
|
+
});
|
|
92
|
+
const sessionService = {
|
|
93
|
+
ensureSessionsDir: vi.fn().mockReturnValue("/tmp/sessions"),
|
|
94
|
+
createRootSessionWithArtifacts: vi.fn().mockResolvedValue({
|
|
95
|
+
manifestPath: "/tmp/manifest.json",
|
|
96
|
+
transcriptPath: "/tmp/transcript.log",
|
|
97
|
+
hookPath: "/tmp/hook.log",
|
|
98
|
+
messagesPath: "/tmp/messages.json",
|
|
99
|
+
manifest,
|
|
100
|
+
}),
|
|
101
|
+
persistSessionMessages: vi.fn(),
|
|
102
|
+
updateSessionStatus: vi.fn().mockResolvedValue({
|
|
103
|
+
updated: true,
|
|
104
|
+
endedAt: "2026-01-01T00:00:05.000Z",
|
|
105
|
+
}),
|
|
106
|
+
writeSessionManifest: vi.fn(),
|
|
107
|
+
listSessions: vi.fn().mockResolvedValue([]),
|
|
108
|
+
deleteSession: vi.fn().mockResolvedValue({ deleted: true }),
|
|
109
|
+
};
|
|
110
|
+
const runtimeBuilder = {
|
|
111
|
+
build: vi.fn().mockReturnValue({
|
|
112
|
+
tools: [],
|
|
113
|
+
shutdown: vi.fn(),
|
|
114
|
+
}),
|
|
115
|
+
};
|
|
116
|
+
const agent = {
|
|
117
|
+
run: vi.fn().mockResolvedValue(createResult()),
|
|
118
|
+
continue: vi.fn().mockResolvedValue(createResult()),
|
|
119
|
+
getMessages: vi.fn().mockReturnValue([]),
|
|
120
|
+
abort: vi.fn(),
|
|
121
|
+
shutdown: vi.fn().mockResolvedValue(undefined),
|
|
122
|
+
};
|
|
123
|
+
const manager = new DefaultSessionManager({
|
|
124
|
+
distinctId,
|
|
125
|
+
sessionService: sessionService as never,
|
|
126
|
+
runtimeBuilder: runtimeBuilder as never,
|
|
127
|
+
createAgent: () => agent as never,
|
|
128
|
+
telemetry,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
await manager.start({
|
|
132
|
+
config: createConfig({ telemetry, sessionId }),
|
|
133
|
+
prompt: "hello",
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
expect(adapter.emit).toHaveBeenCalledWith(
|
|
137
|
+
"session.started",
|
|
138
|
+
expect.objectContaining({
|
|
139
|
+
sessionId,
|
|
140
|
+
distinct_id: distinctId,
|
|
141
|
+
}),
|
|
142
|
+
);
|
|
143
|
+
});
|
|
144
|
+
|
|
73
145
|
it("runs a non-interactive prompt and persists messages/status", async () => {
|
|
74
146
|
const sessionId = "sess-1";
|
|
75
147
|
const manifest = createManifest(sessionId);
|