@dimi-agent/cli 0.6.2 → 0.6.4

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 (2) hide show
  1. package/dist/main.mjs +87 -10
  2. package/package.json +3 -3
package/dist/main.mjs CHANGED
@@ -123100,7 +123100,7 @@ var init_waitService = __esmMin((() => {
123100
123100
  //#region ../../packages/agent-core-v2/src/agent/tools/wait-for/wait-for.md?raw
123101
123101
  var wait_for_default;
123102
123102
  var init_wait_for = __esmMin((() => {
123103
- wait_for_default = "Wait for a future notification when no independent work remains. Provide a concise reason and an optional timeout in seconds. The default is 60 seconds; use longer waits only for clearly long-running work, up to 1800 seconds.\n\nCall WaitFor by itself. It waits on the current agent, not a specific task. Any later notification wakes the agent. A timeout wakes the agent with an explicit `wait_expired` message and never cancels background work.\n";
123103
+ wait_for_default = "Wait for a future notification when no independent work remains. Provide a concise reason and an optional timeout in seconds. The default is 60 seconds; use longer waits only for clearly long-running work, up to 1800 seconds.\n\nCall WaitFor by itself. It waits on the current agent, not a specific task. Any later notification wakes the agent. A timeout wakes the agent with an explicit `wait_expired` message and never cancels background work.\n\nWhen you are waiting on an external state that can change on its own (a file being written, a service coming up, a process finishing, a remote resource becoming ready, …), do not just park on a timeout and re-check later. Start a background Bash task that polls exactly the part of that state you care about and exits as soon as it changes — for example a loop that checks every few seconds and breaks on the expected condition, printing what changed. Because a finished background task notifies the agent, the wait then wakes you the moment the state flips instead of on a blind timeout, and you can act immediately. Keep the polling script narrowly scoped to the monitored condition and make sure it terminates on its own (or after the wait timeout); do not leave a watcher running forever.\n";
123104
123104
  }));
123105
123105
  //#endregion
123106
123106
  //#region ../../packages/agent-core-v2/src/agent/tools/wait-for/waitForTool.ts
@@ -224811,17 +224811,22 @@ var init_sdk_rpc_client = __esmMin((() => {
224811
224811
  }
224812
224812
  /**
224813
224813
  * Build one canonical v2 resume snapshot from the live restored scopes.
224814
- * Replay is the restored context history; task and todo state come from
224815
- * their owning services instead of a second pass over the wire journal.
224814
+ * Replay is the full message history folded from the agent's wire journal —
224815
+ * NOT the live context memory, which after a compaction collapses into
224816
+ * `[...keptUserMessages, compaction_summary]` and would lose the compacted
224817
+ * prefix. `context` keeps the folded (live) context for token accounting;
224818
+ * task and todo state come from their owning services instead of a second
224819
+ * pass over the wire journal.
224816
224820
  */
224817
224821
  async resumedAgentState(session, agent, type, replayTurnLimit) {
224818
224822
  const facade = this.klient.session(session.id).agent(agent.id);
224819
224823
  const ctx = session.accessor.get(ISessionContext);
224820
- const [context, plan, usage, tasks] = await Promise.all([
224824
+ const [context, plan, usage, tasks, replay] = await Promise.all([
224821
224825
  facade.getContext(),
224822
224826
  facade.getPlan(),
224823
224827
  facade.getUsage(),
224824
- facade.getTasks({ activeOnly: false })
224828
+ facade.getTasks({ activeOnly: false }),
224829
+ this.buildReplayFromWire(agent)
224825
224830
  ]);
224826
224831
  const profile = agent.accessor.get(IAgentProfileService).data();
224827
224832
  return {
@@ -224835,11 +224840,7 @@ var init_sdk_rpc_client = __esmMin((() => {
224835
224840
  systemPrompt: profile.systemPrompt
224836
224841
  },
224837
224842
  context,
224838
- replay: limitAgentReplayByTurns(context.history.map((message, time) => ({
224839
- type: "message",
224840
- message,
224841
- time
224842
- })), replayTurnLimit),
224843
+ replay: limitAgentReplayByTurns(replay, replayTurnLimit),
224843
224844
  permission: {
224844
224845
  mode: agent.accessor.get(IAgentPermissionModeService).mode,
224845
224846
  rules: [...agent.accessor.get(IAgentPermissionRulesService).rules]
@@ -224853,6 +224854,63 @@ var init_sdk_rpc_client = __esmMin((() => {
224853
224854
  };
224854
224855
  }
224855
224856
  /**
224857
+ * Fold the agent's full message history from its wire journal.
224858
+ *
224859
+ * The wire journal is the source of truth for message history: it keeps
224860
+ * every `context.append_message` / `context.append_loop_event` record, and
224861
+ * a `context.apply_compaction` record only marks a compaction point instead
224862
+ * of rewriting the past. Folding it yields the complete pre-compaction
224863
+ * history with a summary marker at each compaction, which is what replay
224864
+ * should render. The live context memory (`facade.getContext()`) is the
224865
+ * model's folded context and is deliberately NOT used here — it would hide
224866
+ * everything compacted away.
224867
+ */
224868
+ async buildReplayFromWire(agent) {
224869
+ await agent.accessor.get(IWireService).flush();
224870
+ const scope = agent.accessor.get(IAgentScopeContext).scope();
224871
+ const reducer = createContextTranscriptReducer();
224872
+ const applyCompactionRecords = [];
224873
+ for await (const record of this.engineAccessor.get(IAppendLogStore).read(scope, AGENT_WIRE_RECORD_KEY)) {
224874
+ if (record.type === "context.apply_compaction") applyCompactionRecords.push(record);
224875
+ reducer.add(record);
224876
+ }
224877
+ const { entries, times } = reducer.result();
224878
+ const replay = [];
224879
+ let compactionIndex = 0;
224880
+ for (let i = 0; i < entries.length; i++) {
224881
+ const message = entries[i];
224882
+ const time = times[i];
224883
+ if (message.origin?.kind === "compaction_summary") {
224884
+ const record = applyCompactionRecords[compactionIndex];
224885
+ compactionIndex += 1;
224886
+ if (record !== void 0) {
224887
+ const compaction = readContextCompactionRecord(record);
224888
+ replay.push({
224889
+ type: "compaction",
224890
+ result: {
224891
+ summary: compaction.summary,
224892
+ contextSummary: compaction.contextSummary,
224893
+ compactedCount: compaction.compactedCount,
224894
+ tokensBefore: compaction.tokensBefore,
224895
+ tokensAfter: compaction.tokensAfter,
224896
+ keptUserMessageCount: compaction.keptUserMessageCount,
224897
+ keptHeadUserMessageCount: compaction.keptHeadUserMessageCount,
224898
+ droppedCount: compaction.droppedCount
224899
+ },
224900
+ time: time ?? 0
224901
+ });
224902
+ continue;
224903
+ }
224904
+ }
224905
+ replay.push({
224906
+ type: "message",
224907
+ message,
224908
+ time: time ?? 0
224909
+ });
224910
+ }
224911
+ return replay;
224912
+ }
224913
+ /**
224856
224914
  * Every v2 workspace-id bucket addressing `workDir` (already normalized):
224857
224915
  * the registered workspace's alias set when the catalog knows the root, or
224858
224916
  * the freshly minted bucket key for index-only sessions (mirrors how v1's
@@ -386883,6 +386941,10 @@ var init_session_replay = __esmMin((() => {
386883
386941
  return;
386884
386942
  }
386885
386943
  if (message.origin?.kind === "injection") return;
386944
+ if (message.origin?.kind === "compaction_summary") {
386945
+ this.renderCompactionSummary(context, message);
386946
+ return;
386947
+ }
386886
386948
  if (message.origin?.kind === "task") {
386887
386949
  this.flushAssistant(context);
386888
386950
  const info = this.host.sessionEventHandler.backgroundTasks.get(message.origin.taskId);
@@ -387051,6 +387113,21 @@ var init_session_replay = __esmMin((() => {
387051
387113
  }
387052
387114
  });
387053
387115
  }
387116
+ /**
387117
+ * Render a `compaction_summary` user message folded into the model context
387118
+ * (the resume snapshot's context history carries it after compaction). The
387119
+ * message text is the model-facing summary; token counts are unknown here,
387120
+ * so only the summary is surfaced. The snapshot is still rebuilt from the
387121
+ * wire journal on resume (see `resumedAgentState`), so this branch is a
387122
+ * fallback for snapshots that were built from a folded context.
387123
+ */
387124
+ renderCompactionSummary(context, message) {
387125
+ this.flushAssistant(context);
387126
+ this.host.appendTranscriptEntry({
387127
+ ...replayEntry(context, "status", "Compaction complete", "plain"),
387128
+ compactionData: { summary: contentPartsToText(message.content) }
387129
+ });
387130
+ }
387054
387131
  renderHookResult(context, message) {
387055
387132
  if (message.origin?.kind !== "hook_result") return;
387056
387133
  this.flushAssistant(context);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dimi-agent/cli",
3
- "version": "0.6.2",
3
+ "version": "0.6.4",
4
4
  "description": "The Starting Point for Next-Gen Agents",
5
5
  "keywords": [
6
6
  "agent",
@@ -60,11 +60,11 @@
60
60
  "tsx": "^4.21.0",
61
61
  "yazl": "^3.3.1",
62
62
  "zod": "^4.3.6",
63
+ "@dimi-agent/agent-core-v2": "^0.1.0",
63
64
  "@dimi-agent/dimi-oauth": "^0.1.0",
64
65
  "@dimi-agent/dimi-sdk": "^0.2.0",
65
- "@dimi-agent/dimi-web": "^0.1.0",
66
- "@dimi-agent/agent-core-v2": "^0.1.0",
67
66
  "@dimi-agent/dimi-telemetry": "^0.1.0",
67
+ "@dimi-agent/dimi-web": "^0.1.0",
68
68
  "@dimi-agent/kap-server": "^0.1.0",
69
69
  "@dimi-agent/pi-tui": "^0.1.0",
70
70
  "@dimi-agent/remote": "^0.1.0"