{"version":3,"file":"root.server.cjs","names":["defineRoot","getMaxTasks","TaskStore","TASKS_CHANNEL_TYPE","resolveSessionKey","DelegationManager","createNodeDelegationPlatform","getDelegationTimeoutMs","DOOM_DELEGATION_SERVICE","readDoomDelegationService","removeLegacyStoreDirectoryAsync","sweepStoreFilesAsync","getStoreTtlMs"],"sources":["../../../../../../../src/extensions/workspaces/sessions/(backend)/_lib/root.server.ts"],"sourcesContent":["import { DOOM_DELEGATION_SERVICE, readDoomDelegationService } from '@agimon-ai/doompi-core/delegation';\nimport { defineRoot } from '@agimon-ai/doompi-core/extension-file';\nimport type { DoomServerPluginContext } from '@agimon-ai/doompi-core/server-facet';\nimport type { Context } from '@deepseek-ai/cordis';\n\nimport { getDelegationTimeoutMs, getMaxTasks, getStoreTtlMs } from '../../../../../services/config';\nimport { DelegationManager } from '../../../../../services/delegation';\nimport { createNodeDelegationPlatform } from '../../../../../services/delegationPlatform';\nimport {\n  removeLegacyStoreDirectoryAsync,\n  resolveSessionKey,\n  sweepStoreFilesAsync,\n} from '../../../../../services/paths';\nimport { TaskStore } from '../../../../../services/taskStore';\nimport { TASKS_CHANNEL_TYPE } from '../../../../../types/webTasks';\n\nconst SOURCE = '@agimon-ai/doompi-task';\n\n/** The notification body: one line, since `client.notify` collapses the rest anyway. */\nfunction headlineOf(content: string): string {\n  return content.split('\\n').find((line) => line.trim().length > 0) ?? content;\n}\n\nconst root = defineRoot(({ host: serverHost, agent: host }: DoomServerPluginContext) => {\n  if (!host) throw new Error('Task session requires the headless host.');\n  const execution = host.context;\n  if (serverHost.context.directEvents === undefined)\n    throw new Error('Task headless facet requires the session direct event bus.');\n  const directEvents = serverHost.context.directEvents;\n  const maxTasks = getMaxTasks(execution.environment);\n  const store = new TaskStore({\n    env: execution.environment,\n    onCommitted: (_previous, committed) => {\n      execution.client.setStatus(SOURCE, `tasks: ${committed.tasks.length}`);\n      directEvents.publish(TASKS_CHANNEL_TYPE, execution.sessionId, committed);\n    },\n  });\n  store.configureSession(resolveSessionKey(execution.sessionId, execution.environment));\n  let notifications: Promise<void> = Promise.resolve();\n  const manager = new DelegationManager({\n    store,\n    cwd: execution.cwd,\n    platform: createNodeDelegationPlatform(execution.environment),\n    getSessionId: () => execution.sessionId,\n    notify: (message, options) => {\n      // `DelegationNotifier` is Pi's `sendMessage` shape, and the Pi facet\n      // forwards it verbatim (`root.cli.ts`). A headless session has no such\n      // single call, so the three jobs are done by hand:\n      //\n      //   toast      `client.notify` - operator-facing only, flattened to one\n      //              line and capped at 4096 chars, and the model never sees a\n      //              custom entry. It gets the headline, not the whole result.\n      //   transcript `session.appendCustomEntry` under the same custom type,\n      //              carrying the full multi-line content.\n      //   wake       `session.admitPrompt(content, 'steer')` - the only call\n      //              that puts the completion in front of the model.\n      //              `session.prompt(_, 'steer')` is enqueue-only and parks the\n      //              message on an idle lane, which is why a finished subagent\n      //              used to leave the agent sitting idle.\n      //\n      // Sequenced so two delegations settling in the same tick each observe\n      // settled lane state rather than racing.\n      notifications = notifications\n        .then(async () => {\n          await execution.client.notify({ body: headlineOf(message.content), level: 'info' });\n          await execution.session.appendCustomEntry(message.customType, { content: message.content });\n          // `triggerTurn: false` has no faithful headless mapping - there is no\n          // way to reach model context without starting or joining a turn - so\n          // it stays a toast, as it is today. `DelegationManager` always sends\n          // `true`, so this is defensive rather than live.\n          if (options?.triggerTurn === false) return;\n          // Matching the voice facet, which also refuses rather than degrading:\n          // `session.prompt(_, 'steer')` is NOT a fallback here, because it is\n          // enqueue-only and would park the message on an idle lane - the\n          // original bug.\n          if (!execution.session.admitPrompt) throw new Error('The session cannot admit a task notification.');\n          await execution.session.admitPrompt(message.content, 'steer');\n        })\n        .catch((error: unknown) => {\n          // Mirrors `onNotifyError` below. The delegation is already committed,\n          // so a failed notification costs the model its wake-up, not the\n          // result, and must not stall later notifications.\n          void execution.client.notify({ body: String(error), level: 'warning' });\n        });\n    },\n    onChange: () => execution.client.setStatus(SOURCE, `tasks: ${store.snapshot.tasks.length}`),\n    runTimeoutMs: getDelegationTimeoutMs(execution.environment),\n    onNotifyError: (error) => void execution.client.notify({ body: String(error), level: 'warning' }),\n  });\n  return {\n    value: { store, manager, maxTasks },\n    services: [\n      (serviceContextOwner: Context) => {\n        serviceContextOwner.inject([DOOM_DELEGATION_SERVICE], (serviceContext) => {\n          const service = readDoomDelegationService(serviceContext);\n          if (service) manager.bind(serviceContext, service);\n        });\n      },\n    ],\n    activities: [\n      {\n        name: SOURCE,\n        async start(activityContext) {\n          store.configureSession(resolveSessionKey(activityContext.sessionId, activityContext.environment));\n          await removeLegacyStoreDirectoryAsync(store.storePath, activityContext.cwd);\n          if (!activityContext.environment.DOOM_TASK_STORE_PATH)\n            await sweepStoreFilesAsync(store.storePath, getStoreTtlMs(activityContext.environment));\n          await store.readAsync();\n          await manager.reconcile();\n          execution.client.setStatus(SOURCE, `tasks: ${store.snapshot.tasks.length}`);\n          return () => {\n            manager.reset();\n            execution.client.setStatus(SOURCE, undefined);\n          };\n        },\n      },\n    ],\n    onDispose() {\n      manager.dispose();\n      store.dispose();\n    },\n  };\n});\n\nexport type TaskServerScope = Awaited<ReturnType<typeof root>>['value'];\nexport default root;\n"],"mappings":"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"}