@joshski/dust 0.1.78 → 0.1.79

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.
@@ -40,4 +40,15 @@ export interface EventMessage {
40
40
  * is forwarded as a claude-event.
41
41
  */
42
42
  export declare function rawEventToAgentEvent(rawEvent: Record<string, unknown>): AgentSessionEvent;
43
+ /**
44
+ * Create a heartbeat throttler that limits agent-session-activity events
45
+ * to at most once per interval (default: 5 seconds).
46
+ *
47
+ * The returned callback converts raw Claude events to AgentSessionEvents,
48
+ * throttling stream_event heartbeats while forwarding all other events.
49
+ */
50
+ export declare function createHeartbeatThrottler(onAgentEvent: (event: AgentSessionEvent) => void, options?: {
51
+ intervalMs?: number;
52
+ now?: () => number;
53
+ }): (rawEvent: Record<string, unknown>) => void;
43
54
  export declare function formatAgentEvent(event: AgentSessionEvent): string | null;
@@ -18,7 +18,9 @@ export interface TaskGraph {
18
18
  }
19
19
  export { CAPTURE_IDEA_PREFIX, findAllWorkflowTasks, parseOpenQuestions };
20
20
  export type { IdeaInProgress };
21
+ export type ArtifactType = 'ideas' | 'tasks' | 'principles' | 'facts';
21
22
  export interface ArtifactsRepository {
23
+ artifactPath(type: ArtifactType, slug: string): string;
22
24
  parseIdea(options: {
23
25
  slug: string;
24
26
  }): Promise<Idea>;
@@ -63,4 +65,4 @@ export interface ArtifactsRepository {
63
65
  buildTaskGraph(): Promise<TaskGraph>;
64
66
  }
65
67
  export declare function buildArtifactsRepository(fileSystem: FileSystem, dustPath: string): ArtifactsRepository;
66
- export declare function buildReadOnlyArtifactsRepository(fileSystem: ReadableFileSystem, dustPath: string): Pick<ArtifactsRepository, 'parseIdea' | 'listIdeas' | 'parsePrinciple' | 'listPrinciples' | 'parseFact' | 'listFacts' | 'parseTask' | 'listTasks' | 'findWorkflowTaskForIdea' | 'parseCaptureIdeaTask' | 'buildTaskGraph'>;
68
+ export declare function buildReadOnlyArtifactsRepository(fileSystem: ReadableFileSystem, dustPath: string): Pick<ArtifactsRepository, 'artifactPath' | 'parseIdea' | 'listIdeas' | 'parsePrinciple' | 'listPrinciples' | 'parseFact' | 'listFacts' | 'parseTask' | 'listTasks' | 'findWorkflowTaskForIdea' | 'parseCaptureIdeaTask' | 'buildTaskGraph'>;
package/dist/artifacts.js CHANGED
@@ -548,6 +548,9 @@ async function parseCaptureIdeaTask(fileSystem, dustPath, taskSlug) {
548
548
  // lib/artifacts/index.ts
549
549
  function buildArtifactsRepository(fileSystem, dustPath) {
550
550
  return {
551
+ artifactPath(type, slug) {
552
+ return `${dustPath}/${type}/${slug}.md`;
553
+ },
551
554
  async parseIdea(options) {
552
555
  return parseIdea(fileSystem, dustPath, options.slug);
553
556
  },
@@ -635,6 +638,9 @@ function buildArtifactsRepository(fileSystem, dustPath) {
635
638
  }
636
639
  function buildReadOnlyArtifactsRepository(fileSystem, dustPath) {
637
640
  return {
641
+ artifactPath(type, slug) {
642
+ return `${dustPath}/${type}/${slug}.md`;
643
+ },
638
644
  async parseIdea(options) {
639
645
  return parseIdea(fileSystem, dustPath, options.slug);
640
646
  },
package/dist/dust.js CHANGED
@@ -306,7 +306,7 @@ async function loadSettings(cwd, fileSystem) {
306
306
  }
307
307
 
308
308
  // lib/version.ts
309
- var DUST_VERSION = "0.1.78";
309
+ var DUST_VERSION = "0.1.79";
310
310
 
311
311
  // lib/session.ts
312
312
  var DUST_UNATTENDED = "DUST_UNATTENDED";
@@ -2484,6 +2484,23 @@ function rawEventToAgentEvent(rawEvent) {
2484
2484
  }
2485
2485
  return { type: "claude-event", rawEvent };
2486
2486
  }
2487
+ var DEFAULT_HEARTBEAT_INTERVAL_MS = 5000;
2488
+ function createHeartbeatThrottler(onAgentEvent, options) {
2489
+ const intervalMs = options?.intervalMs ?? DEFAULT_HEARTBEAT_INTERVAL_MS;
2490
+ const now = options?.now ?? Date.now;
2491
+ let lastHeartbeatTime;
2492
+ return (rawEvent) => {
2493
+ const event = rawEventToAgentEvent(rawEvent);
2494
+ if (event.type === "agent-session-activity") {
2495
+ const currentTime = now();
2496
+ if (lastHeartbeatTime !== undefined && currentTime - lastHeartbeatTime < intervalMs) {
2497
+ return;
2498
+ }
2499
+ lastHeartbeatTime = currentTime;
2500
+ }
2501
+ onAgentEvent(event);
2502
+ };
2503
+ }
2487
2504
  function agentDisplayName(agentType) {
2488
2505
  if (agentType === "codex")
2489
2506
  return "Codex";
@@ -2942,9 +2959,7 @@ async function loopClaude(dependencies, loopDependencies = createDefaultDependen
2942
2959
  let completedIterations = 0;
2943
2960
  const iterationOptions = { hooksInstalled };
2944
2961
  if (eventsUrl) {
2945
- iterationOptions.onRawEvent = (rawEvent) => {
2946
- onAgentEvent(rawEventToAgentEvent(rawEvent));
2947
- };
2962
+ iterationOptions.onRawEvent = createHeartbeatThrottler(onAgentEvent);
2948
2963
  }
2949
2964
  while (completedIterations < maxIterations) {
2950
2965
  agentSessionId = crypto.randomUUID();
@@ -3105,9 +3120,7 @@ async function runRepositoryLoop(repoState, repoDeps, sendEvent, sessionId) {
3105
3120
  hooksInstalled,
3106
3121
  signal: abortController.signal,
3107
3122
  repositoryId: repoState.repository.id.toString(),
3108
- onRawEvent: (rawEvent) => {
3109
- onAgentEvent(rawEventToAgentEvent(rawEvent));
3110
- }
3123
+ onRawEvent: createHeartbeatThrottler(onAgentEvent)
3111
3124
  });
3112
3125
  } catch (error) {
3113
3126
  const msg = error instanceof Error ? error.message : String(error);
package/dist/types.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  */
7
7
  export type { AgentSessionEvent, EventMessage } from './agent-events';
8
8
  export type { Idea, IdeaOpenQuestion, IdeaOption } from './artifacts/ideas';
9
- export type { TaskGraph, TaskGraphNode } from './artifacts/index';
9
+ export type { ArtifactType, TaskGraph, TaskGraphNode } from './artifacts/index';
10
10
  export type { Task } from './artifacts/tasks';
11
11
  export type { CreateIdeaTransitionTaskResult, DecomposeIdeaOptions, IdeaInProgress, OpenQuestionResponse, ParsedCaptureIdeaTask, WorkflowTaskMatch, WorkflowTaskType, } from './artifacts/workflow-tasks';
12
12
  export type { Repository } from './bucket/repository';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joshski/dust",
3
- "version": "0.1.78",
3
+ "version": "0.1.79",
4
4
  "description": "Flow state for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {