@clinebot/core 0.0.6 → 0.0.10

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.
Files changed (83) hide show
  1. package/dist/agents/hooks-config-loader.d.ts +1 -0
  2. package/dist/auth/cline.d.ts +2 -0
  3. package/dist/auth/codex.d.ts +5 -1
  4. package/dist/auth/oca.d.ts +7 -1
  5. package/dist/auth/types.d.ts +2 -0
  6. package/dist/index.d.ts +3 -1
  7. package/dist/index.node.d.ts +2 -0
  8. package/dist/index.node.js +164 -162
  9. package/dist/input/mention-enricher.d.ts +1 -0
  10. package/dist/providers/local-provider-service.d.ts +1 -1
  11. package/dist/runtime/session-runtime.d.ts +1 -1
  12. package/dist/session/default-session-manager.d.ts +13 -17
  13. package/dist/session/rpc-spawn-lease.d.ts +7 -0
  14. package/dist/session/runtime-oauth-token-manager.d.ts +4 -2
  15. package/dist/session/session-agent-events.d.ts +15 -0
  16. package/dist/session/session-config-builder.d.ts +13 -0
  17. package/dist/session/session-manager.d.ts +2 -2
  18. package/dist/session/session-team-coordination.d.ts +12 -0
  19. package/dist/session/session-telemetry.d.ts +9 -0
  20. package/dist/session/unified-session-persistence-service.d.ts +12 -16
  21. package/dist/session/utils/helpers.d.ts +1 -1
  22. package/dist/session/utils/types.d.ts +1 -1
  23. package/dist/storage/provider-settings-legacy-migration.d.ts +25 -0
  24. package/dist/telemetry/core-events.d.ts +122 -0
  25. package/dist/tools/definitions.d.ts +1 -1
  26. package/dist/tools/executors/file-read.d.ts +1 -1
  27. package/dist/tools/index.d.ts +1 -1
  28. package/dist/tools/presets.d.ts +1 -1
  29. package/dist/tools/schemas.d.ts +48 -11
  30. package/dist/tools/types.d.ts +3 -3
  31. package/dist/types/config.d.ts +1 -1
  32. package/dist/types/events.d.ts +1 -1
  33. package/dist/types/provider-settings.d.ts +4 -4
  34. package/dist/types.d.ts +1 -1
  35. package/package.json +4 -3
  36. package/src/agents/hooks-config-loader.ts +2 -0
  37. package/src/auth/cline.ts +35 -1
  38. package/src/auth/codex.ts +27 -2
  39. package/src/auth/oca.ts +31 -4
  40. package/src/auth/types.ts +3 -0
  41. package/src/index.node.ts +4 -0
  42. package/src/index.ts +27 -0
  43. package/src/input/file-indexer.test.ts +40 -0
  44. package/src/input/file-indexer.ts +21 -0
  45. package/src/input/mention-enricher.test.ts +3 -0
  46. package/src/input/mention-enricher.ts +3 -0
  47. package/src/providers/local-provider-service.ts +6 -7
  48. package/src/runtime/hook-file-hooks.test.ts +51 -1
  49. package/src/runtime/hook-file-hooks.ts +91 -11
  50. package/src/runtime/session-runtime.ts +1 -1
  51. package/src/session/default-session-manager.e2e.test.ts +2 -1
  52. package/src/session/default-session-manager.ts +367 -601
  53. package/src/session/rpc-spawn-lease.test.ts +49 -0
  54. package/src/session/rpc-spawn-lease.ts +122 -0
  55. package/src/session/runtime-oauth-token-manager.ts +21 -14
  56. package/src/session/session-agent-events.ts +159 -0
  57. package/src/session/session-config-builder.ts +111 -0
  58. package/src/session/session-graph.ts +2 -0
  59. package/src/session/session-host.ts +21 -0
  60. package/src/session/session-manager.ts +2 -2
  61. package/src/session/session-team-coordination.ts +198 -0
  62. package/src/session/session-telemetry.ts +95 -0
  63. package/src/session/unified-session-persistence-service.test.ts +81 -0
  64. package/src/session/unified-session-persistence-service.ts +470 -469
  65. package/src/session/utils/helpers.ts +1 -1
  66. package/src/session/utils/types.ts +1 -1
  67. package/src/storage/provider-settings-legacy-migration.test.ts +133 -1
  68. package/src/storage/provider-settings-legacy-migration.ts +63 -11
  69. package/src/telemetry/core-events.ts +344 -0
  70. package/src/tools/definitions.test.ts +203 -36
  71. package/src/tools/definitions.ts +66 -28
  72. package/src/tools/executors/editor.test.ts +35 -0
  73. package/src/tools/executors/editor.ts +33 -46
  74. package/src/tools/executors/file-read.test.ts +29 -5
  75. package/src/tools/executors/file-read.ts +17 -6
  76. package/src/tools/index.ts +2 -0
  77. package/src/tools/presets.ts +1 -1
  78. package/src/tools/schemas.ts +88 -38
  79. package/src/tools/types.ts +7 -3
  80. package/src/types/config.ts +1 -1
  81. package/src/types/events.ts +6 -1
  82. package/src/types/provider-settings.ts +6 -6
  83. package/src/types.ts +1 -1
@@ -30,6 +30,9 @@ type AgentHookToolCallEndContext = Parameters<
30
30
  type AgentHookTurnEndContext = Parameters<
31
31
  NonNullable<AgentHooks["onTurnEnd"]>
32
32
  >[0];
33
+ type AgentHookStopErrorContext = Parameters<
34
+ NonNullable<AgentHooks["onStopError"]>
35
+ >[0];
33
36
  type AgentHookSessionShutdownContext = Parameters<
34
37
  NonNullable<AgentHooks["onSessionShutdown"]>
35
38
  >[0];
@@ -201,6 +204,43 @@ function parseHookStdout(stdout: string): {
201
204
  }
202
205
  }
203
206
 
207
+ async function writeToChildStdin(
208
+ child: ReturnType<typeof spawn>,
209
+ body: string,
210
+ ): Promise<void> {
211
+ const stdin = child.stdin;
212
+ if (!stdin) {
213
+ throw new Error("hook command failed to create stdin");
214
+ }
215
+
216
+ await new Promise<void>((resolve, reject) => {
217
+ let settled = false;
218
+ const finish = (error?: Error | null) => {
219
+ if (settled) {
220
+ return;
221
+ }
222
+ settled = true;
223
+ stdin.off("error", onError);
224
+ stdin.off("close", onClose);
225
+ if (error) {
226
+ const code = (error as Error & { code?: string }).code;
227
+ if (code === "EPIPE" || code === "ERR_STREAM_DESTROYED") {
228
+ resolve();
229
+ return;
230
+ }
231
+ reject(error);
232
+ return;
233
+ }
234
+ resolve();
235
+ };
236
+ const onError = (error: Error) => finish(error);
237
+ const onClose = () => finish();
238
+ stdin.on("error", onError);
239
+ stdin.once("close", onClose);
240
+ stdin.end(body, (error?: Error | null) => finish(error));
241
+ });
242
+ }
243
+
204
244
  async function runHookCommand(
205
245
  payload: HookEventPayload,
206
246
  options: {
@@ -222,19 +262,18 @@ async function runHookCommand(
222
262
  : ["pipe", "pipe", "pipe"],
223
263
  detached: options.detached,
224
264
  });
265
+ const spawned = new Promise<void>((resolve) => {
266
+ child.once("spawn", () => resolve());
267
+ });
268
+ const childError = new Promise<never>((_, reject) => {
269
+ child.once("error", (error) => reject(error));
270
+ });
225
271
 
226
272
  const body = JSON.stringify(payload);
227
- if (!child.stdin) {
228
- throw new Error("hook command failed to create stdin");
229
- }
230
- child.stdin.write(body);
231
- child.stdin.end();
273
+ await writeToChildStdin(child, body);
232
274
 
233
275
  if (options.detached) {
234
- await new Promise<void>((resolve, reject) => {
235
- child.once("error", reject);
236
- child.once("spawn", () => resolve());
237
- });
276
+ await Promise.race([spawned, childError]);
238
277
  child.unref();
239
278
  return;
240
279
  }
@@ -253,8 +292,7 @@ async function runHookCommand(
253
292
  stderr += chunk.toString();
254
293
  });
255
294
 
256
- return await new Promise<HookCommandResult>((resolve, reject) => {
257
- child.once("error", reject);
295
+ const result = new Promise<HookCommandResult>((resolve) => {
258
296
  if ((options.timeoutMs ?? 0) > 0) {
259
297
  timeoutId = setTimeout(() => {
260
298
  timedOut = true;
@@ -276,6 +314,7 @@ async function runHookCommand(
276
314
  });
277
315
  });
278
316
  });
317
+ return await Promise.race([result, childError]);
279
318
  }
280
319
 
281
320
  function parseShebangCommand(path: string): string[] | undefined {
@@ -491,6 +530,19 @@ export function createHookAuditHooks(options: {
491
530
  });
492
531
  return undefined;
493
532
  },
533
+ onStopError: async (ctx: AgentHookStopErrorContext) => {
534
+ append({
535
+ ...createPayloadBase(ctx, runtimeOptions),
536
+ hookName: "agent_error",
537
+ iteration: ctx.iteration,
538
+ error: {
539
+ name: ctx.error.name,
540
+ message: ctx.error.message,
541
+ stack: ctx.error.stack,
542
+ },
543
+ });
544
+ return undefined;
545
+ },
494
546
  onSessionShutdown: async (ctx: AgentHookSessionShutdownContext) => {
495
547
  if (isAbortReason(ctx.reason)) {
496
548
  append({
@@ -634,6 +686,30 @@ export function createHookConfigFileHooks(
634
686
  });
635
687
  };
636
688
 
689
+ const runStopError = async (
690
+ ctx: AgentHookStopErrorContext,
691
+ ): Promise<void> => {
692
+ const commandPaths = commandMap.agent_error ?? [];
693
+ if (commandPaths.length === 0) {
694
+ return;
695
+ }
696
+ runAsyncHookCommands({
697
+ commands: commandPaths,
698
+ cwd: options.cwd,
699
+ logger: options.logger,
700
+ payload: {
701
+ ...createPayloadBase(ctx, options),
702
+ hookName: "agent_error",
703
+ iteration: ctx.iteration,
704
+ error: {
705
+ name: ctx.error.name,
706
+ message: ctx.error.message,
707
+ stack: ctx.error.stack,
708
+ },
709
+ },
710
+ });
711
+ };
712
+
637
713
  const runSessionShutdown = async (
638
714
  ctx: AgentHookSessionShutdownContext,
639
715
  ): Promise<void> => {
@@ -684,6 +760,10 @@ export function createHookConfigFileHooks(
684
760
  await runTurnEnd(ctx);
685
761
  return undefined;
686
762
  },
763
+ onStopError: async (ctx: AgentHookStopErrorContext) => {
764
+ await runStopError(ctx);
765
+ return undefined;
766
+ },
687
767
  onSessionShutdown: async (ctx: AgentHookSessionShutdownContext) => {
688
768
  await runSessionShutdown(ctx);
689
769
  return undefined;
@@ -40,7 +40,7 @@ export interface RuntimeBuilder {
40
40
  export interface SessionRuntime {
41
41
  start(config: CoreSessionConfig): Promise<{ sessionId: string }>;
42
42
  send(sessionId: string, prompt: string): Promise<AgentResult | undefined>;
43
- abort(sessionId: string): Promise<void>;
43
+ abort(sessionId: string, reason?: unknown): Promise<void>;
44
44
  stop(sessionId: string): Promise<void>;
45
45
  poll(): Promise<string[]>;
46
46
  }
@@ -10,7 +10,7 @@ import {
10
10
  import { tmpdir } from "node:os";
11
11
  import { join } from "node:path";
12
12
  import type { AgentResult } from "@clinebot/agents";
13
- import type { providers as LlmsProviders } from "@clinebot/llms";
13
+ import type { LlmsProviders } from "@clinebot/llms";
14
14
  import { nanoid } from "nanoid";
15
15
  import { afterEach, describe, expect, it, vi } from "vitest";
16
16
  import type { SessionSource, SessionStatus } from "../types/common";
@@ -348,6 +348,7 @@ describe("DefaultSessionManager e2e", () => {
348
348
  await manager.stop(started.sessionId);
349
349
  const stopped = await manager.get(started.sessionId);
350
350
  expect(stopped?.status).toBe("cancelled");
351
+ expect(stopped?.exitCode).toBe(0);
351
352
  expect(agentShutdown).toHaveBeenCalledTimes(1);
352
353
  expect(runtimeShutdown).toHaveBeenCalledTimes(1);
353
354
  const parsedManifest = JSON.parse(