saeeol 1.1.1 → 1.2.1
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/package.json +14 -14
- package/script/build.ts +1 -1
- package/src/addons/addon-analytics.ts +1 -1
- package/src/cli/cmd/tui/routes/session/suggest.tsx +1 -1
- package/src/cli/logo.ts +1 -1
- package/src/cli/ui.ts +1 -1
- package/src/config/config-loader.ts +1 -1
- package/src/config/config-schema.ts +1 -1
- package/src/config/config.ts +1 -1
- package/src/config/markdown.ts +1 -1
- package/src/index.ts +2 -2
- package/src/lsp/lsp.ts +1 -1
- package/src/lsp/server-web.ts +1 -1
- package/src/mcp/oauth-callback.ts +1 -1
- package/src/{saeeol → overlay}/encoding.ts +1 -1
- package/src/{saeeol → overlay}/text-stream.ts +1 -1
- package/src/{saeeol → overlay}/tool/encoded-io.ts +1 -1
- package/src/patch/patch-apply.ts +1 -1
- package/src/patch/patch-parse.ts +1 -1
- package/src/session/compaction-helpers.ts +1 -169
- package/src/session/compaction.ts +1 -712
- package/src/session/core/compaction/compaction-helpers.ts +169 -0
- package/src/session/core/compaction/compaction.ts +712 -0
- package/src/session/core/compaction/overflow.ts +28 -0
- package/src/session/core/instruction.ts +234 -0
- package/src/session/core/llm.ts +504 -0
- package/src/session/core/network.ts +392 -0
- package/src/session/core/processor.ts +731 -0
- package/src/session/core/projectors.ts +139 -0
- package/src/session/core/resolve-tools.ts +241 -0
- package/src/session/core/retry.ts +149 -0
- package/src/session/core/revert.ts +173 -0
- package/src/session/core/run-state.ts +110 -0
- package/src/session/core/schema.ts +35 -0
- package/src/session/core/session-types.ts +160 -0
- package/src/session/core/session.sql.ts +124 -0
- package/src/session/core/session.ts +948 -0
- package/src/session/core/shell-exec.ts +205 -0
- package/src/session/core/status.ts +100 -0
- package/src/session/core/subtask.ts +268 -0
- package/src/session/core/summary.ts +173 -0
- package/src/session/core/system.ts +114 -0
- package/src/session/core/todo.ts +86 -0
- package/src/session/core/user-part.ts +293 -0
- package/src/session/instruction.ts +1 -234
- package/src/session/llm.ts +1 -504
- package/src/session/message/message-errors.ts +83 -0
- package/src/session/message/message-parts.ts +89 -0
- package/src/session/message/message-query.ts +107 -0
- package/src/session/message/message-transform.ts +156 -0
- package/src/session/message/message-types.ts +68 -0
- package/src/session/message/message-v2.ts +73 -0
- package/src/session/message/message.ts +192 -0
- package/src/session/message-errors.ts +1 -83
- package/src/session/message-parts.ts +1 -89
- package/src/session/message-query.ts +1 -107
- package/src/session/message-transform.ts +1 -156
- package/src/session/message-types.ts +1 -68
- package/src/session/message-v2.ts +1 -73
- package/src/session/message.ts +1 -192
- package/src/session/network.ts +1 -392
- package/src/session/overflow.ts +1 -28
- package/src/session/processor.ts +1 -731
- package/src/session/projectors.ts +2 -139
- package/src/session/prompt/prompt-command.ts +93 -0
- package/src/session/prompt/prompt-loop.ts +299 -0
- package/src/session/prompt/prompt-model.ts +44 -0
- package/src/session/prompt/prompt-reminders.ts +120 -0
- package/src/session/prompt/prompt-resolve.ts +42 -0
- package/src/session/prompt/prompt-schemas.ts +128 -0
- package/src/session/prompt/prompt-title.ts +55 -0
- package/src/session/prompt/prompt-types.ts +47 -0
- package/src/session/prompt/prompt-user-msg.ts +80 -0
- package/src/session/prompt/prompt.ts +211 -0
- package/src/session/prompt-command.ts +1 -93
- package/src/session/prompt-loop.ts +1 -299
- package/src/session/prompt-model.ts +1 -44
- package/src/session/prompt-reminders.ts +1 -120
- package/src/session/prompt-resolve.ts +1 -42
- package/src/session/prompt-schemas.ts +1 -128
- package/src/session/prompt-title.ts +1 -55
- package/src/session/prompt-types.ts +1 -47
- package/src/session/prompt-user-msg.ts +1 -80
- package/src/session/prompt.ts +1 -211
- package/src/session/resolve-tools.ts +1 -241
- package/src/session/retry.ts +1 -149
- package/src/session/revert.ts +1 -173
- package/src/session/run-state.ts +1 -110
- package/src/session/schema.ts +1 -35
- package/src/session/session-types.ts +1 -160
- package/src/session/session.sql.ts +1 -124
- package/src/session/session.ts +1 -948
- package/src/session/shell-exec.ts +1 -205
- package/src/session/status.ts +1 -100
- package/src/session/subtask.ts +1 -268
- package/src/session/summary.ts +1 -173
- package/src/session/system.ts +1 -114
- package/src/session/todo.ts +1 -86
- package/src/session/user-part.ts +1 -293
- package/src/skill/index.ts +1 -1
- package/src/suggestion/index.ts +1 -1
- package/src/tool/apply_patch.ts +2 -2
- package/src/tool/edit.ts +2 -2
- package/src/tool/read.ts +2 -2
- package/src/tool/recall.ts +1 -1
- package/src/tool/registry.ts +2 -2
- package/src/tool/suggest.ts +1 -1
- package/src/tool/task.ts +3 -3
- package/src/tool/todo.ts +1 -1
- package/src/tool/write.ts +2 -2
- package/test/lsp/index.test.ts +1 -1
- package/test/saeeol/agent-manager-tool.test.ts +1 -1
- package/test/saeeol/ask-agent-permissions.test.ts +1 -1
- package/test/saeeol/bash-hierarchy.test.ts +1 -1
- package/test/saeeol/builtin-skills.test.ts +1 -1
- package/test/saeeol/cli/dev-setup.test.ts +1 -1
- package/test/saeeol/cli/roll-call.test.ts +1 -1
- package/test/saeeol/cli-run-auto-helper.test.ts +1 -1
- package/test/saeeol/codex-auth-refresh.test.ts +1 -1
- package/test/saeeol/commit-message/generate.test.ts +1 -1
- package/test/saeeol/commit-message/git-context.test.ts +1 -1
- package/test/saeeol/commit-message-windows.test.ts +1 -1
- package/test/saeeol/compaction-payload-recovery.test.ts +1 -1
- package/test/saeeol/config/config.test.ts +1 -1
- package/test/saeeol/config-injector.test.ts +1 -1
- package/test/saeeol/config-validation.test.ts +1 -1
- package/test/saeeol/cost-propagation.test.ts +1 -1
- package/test/saeeol/custom-provider-delete.test.ts +1 -1
- package/test/saeeol/diff-full.test.ts +1 -1
- package/test/saeeol/encoding.test.ts +1 -1
- package/test/saeeol/enhance-prompt.test.ts +1 -1
- package/test/saeeol/ensure-plan-dir.test.ts +1 -1
- package/test/saeeol/errors.test.ts +1 -1
- package/test/saeeol/help.test.ts +3 -3
- package/test/saeeol/ignore-migrator.test.ts +1 -1
- package/test/saeeol/indexing-auth.test.ts +1 -1
- package/test/saeeol/indexing-feature.test.ts +1 -1
- package/test/saeeol/indexing-label.test.ts +1 -1
- package/test/saeeol/indexing-startup.test.ts +1 -1
- package/test/saeeol/indexing-worktree.test.ts +1 -1
- package/test/saeeol/lancedb-runtime.test.ts +9 -9
- package/test/saeeol/logo.test.ts +1 -1
- package/test/saeeol/lsp-typescript-lightweight.test.ts +2 -2
- package/test/saeeol/mcp-migrator.test.ts +1 -1
- package/test/saeeol/model-info-panel-utils.test.ts +1 -1
- package/test/saeeol/modes-migrator.test.ts +1 -1
- package/test/saeeol/paths.test.ts +1 -1
- package/test/saeeol/permission/config-paths.test.ts +2 -2
- package/test/saeeol/permission/external-directory-allow.test.ts +1 -1
- package/test/saeeol/plan-exit-detection.test.ts +1 -1
- package/test/saeeol/plan-followup.test.ts +2 -2
- package/test/saeeol/project-id.test.ts +1 -1
- package/test/saeeol/question-dismiss-all.test.ts +1 -1
- package/test/saeeol/rules-migrator.test.ts +1 -1
- package/test/saeeol/semantic-search.test.ts +2 -2
- package/test/saeeol/session/platform-attribution.test.ts +1 -1
- package/test/saeeol/session-compaction-cap.test.ts +2 -2
- package/test/saeeol/session-compaction-chunks.test.ts +1 -1
- package/test/saeeol/session-compaction-safety.test.ts +1 -1
- package/test/saeeol/session-import-service.test.ts +1 -1
- package/test/saeeol/session-processor-empty-tool-calls.test.ts +1 -1
- package/test/saeeol/session-processor-review-telemetry.test.ts +1 -1
- package/test/saeeol/session-prompt-queue.test.ts +1 -1
- package/test/saeeol/sessions/remote-sender.test.ts +1 -1
- package/test/saeeol/snapshot-track-timeout.test.ts +1 -1
- package/test/saeeol/suggestion/auto-dismiss.test.ts +2 -2
- package/test/saeeol/suggestion/suggestion.test.ts +1 -1
- package/test/saeeol/suggestion/tool.test.ts +2 -2
- package/test/saeeol/system-prompt.test.ts +1 -1
- package/test/saeeol/todo-view.test.ts +1 -1
- package/test/saeeol/tool-registry-indexing.test.ts +3 -3
- package/test/saeeol/tui-diff.test.ts +1 -1
- package/test/saeeol/tui-sync.test.ts +1 -1
- package/test/saeeol/util/url.test.ts +1 -1
- package/test/saeeol/workflows-migrator.test.ts +1 -1
- package/test/saeeol/worktree-diff-summary.test.ts +1 -1
- package/tsconfig.json +1 -1
- /package/src/{saeeol → overlay}/agent/agent-remove.ts +0 -0
- /package/src/{saeeol → overlay}/agent/index.ts +0 -0
- /package/src/{saeeol → overlay}/agent/patch-agents.ts +0 -0
- /package/src/{saeeol → overlay}/agent/permissions.ts +0 -0
- /package/src/{saeeol → overlay}/agent-manager/event.ts +0 -0
- /package/src/{saeeol → overlay}/bash-hierarchy.ts +0 -0
- /package/src/{saeeol → overlay}/bell.ts +0 -0
- /package/src/{saeeol → overlay}/bootstrap.ts +0 -0
- /package/src/{saeeol → overlay}/claw/autocomplete-popup.tsx +0 -0
- /package/src/{saeeol → overlay}/claw/autocomplete-ref.ts +0 -0
- /package/src/{saeeol → overlay}/claw/autocomplete-types.ts +0 -0
- /package/src/{saeeol → overlay}/claw/autocomplete.tsx +0 -0
- /package/src/{saeeol → overlay}/claw/chat-client.ts +0 -0
- /package/src/{saeeol → overlay}/claw/chat.tsx +0 -0
- /package/src/{saeeol → overlay}/claw/client-events.ts +0 -0
- /package/src/{saeeol → overlay}/claw/client-helpers.ts +0 -0
- /package/src/{saeeol → overlay}/claw/client.ts +0 -0
- /package/src/{saeeol → overlay}/claw/dialog-conversation-list.tsx +0 -0
- /package/src/{saeeol → overlay}/claw/event-service-client-core.ts +0 -0
- /package/src/{saeeol → overlay}/claw/event-service-client-impl.ts +0 -0
- /package/src/{saeeol → overlay}/claw/event-service-client.ts +0 -0
- /package/src/{saeeol → overlay}/claw/hooks.ts +0 -0
- /package/src/{saeeol → overlay}/claw/sidebar.tsx +0 -0
- /package/src/{saeeol → overlay}/claw/types.ts +0 -0
- /package/src/{saeeol → overlay}/claw/view.tsx +0 -0
- /package/src/{saeeol → overlay}/cli/cmd/roll-call-call.ts +0 -0
- /package/src/{saeeol → overlay}/cli/cmd/roll-call-format.ts +0 -0
- /package/src/{saeeol → overlay}/cli/cmd/roll-call.ts +0 -0
- /package/src/{saeeol → overlay}/cli/cmd/tui/app.tsx +0 -0
- /package/src/{saeeol → overlay}/cli/cmd/tui/component/dialog-provider.tsx +0 -0
- /package/src/{saeeol → overlay}/cli/cmd/tui/feedback.ts +0 -0
- /package/src/{saeeol → overlay}/cli/cmd/tui/util/terminal.ts +0 -0
- /package/src/{saeeol → overlay}/cli/dev-setup-utils.ts +0 -0
- /package/src/{saeeol → overlay}/cli/dev-setup.ts +0 -0
- /package/src/{saeeol → overlay}/cli/heap-snapshot.ts +0 -0
- /package/src/{saeeol → overlay}/cli/logo.ts +0 -0
- /package/src/{saeeol → overlay}/cli/run-auto.ts +0 -0
- /package/src/{saeeol → overlay}/cli/saeeol-logo.ts +0 -0
- /package/src/{saeeol → overlay}/cloud-session.ts +0 -0
- /package/src/{saeeol → overlay}/commands-index.ts +0 -0
- /package/src/{saeeol → overlay}/commands.ts +0 -0
- /package/src/{saeeol → overlay}/commands.tsx +0 -0
- /package/src/{saeeol → overlay}/commit-message/generate.ts +0 -0
- /package/src/{saeeol → overlay}/commit-message/git-context.ts +0 -0
- /package/src/{saeeol → overlay}/commit-message/index.ts +0 -0
- /package/src/{saeeol → overlay}/commit-message/types.ts +0 -0
- /package/src/{saeeol → overlay}/components/dialog-auto-method.tsx +0 -0
- /package/src/{saeeol → overlay}/components/dialog-claw-setup.tsx +0 -0
- /package/src/{saeeol → overlay}/components/dialog-claw-upgrade.tsx +0 -0
- /package/src/{saeeol → overlay}/components/dialog-indexing-helpers.ts +0 -0
- /package/src/{saeeol → overlay}/components/dialog-indexing.tsx +0 -0
- /package/src/{saeeol → overlay}/components/dialog-notifications.tsx +0 -0
- /package/src/{saeeol → overlay}/components/dialog-organization.tsx +0 -0
- /package/src/{saeeol → overlay}/components/dialog-profile.tsx +0 -0
- /package/src/{saeeol → overlay}/components/dialog-provider-settings.tsx +0 -0
- /package/src/{saeeol → overlay}/components/dialog-team-select.tsx +0 -0
- /package/src/{saeeol → overlay}/components/dialog-tuning.tsx +0 -0
- /package/src/{saeeol → overlay}/components/dialog-vector-store.tsx +0 -0
- /package/src/{saeeol → overlay}/components/error-display.tsx +0 -0
- /package/src/{saeeol → overlay}/components/model-info-panel-utils.ts +0 -0
- /package/src/{saeeol → overlay}/components/model-info-panel.tsx +0 -0
- /package/src/{saeeol → overlay}/components/news.tsx +0 -0
- /package/src/{saeeol → overlay}/components/notification-banner.tsx +0 -0
- /package/src/{saeeol → overlay}/components/session-indexing.tsx +0 -0
- /package/src/{saeeol → overlay}/components/tips.tsx +0 -0
- /package/src/{saeeol → overlay}/config/config-core.ts +0 -0
- /package/src/{saeeol → overlay}/config/config-helpers.ts +0 -0
- /package/src/{saeeol → overlay}/config/config-legacy.ts +0 -0
- /package/src/{saeeol → overlay}/config/config.ts +0 -0
- /package/src/{saeeol → overlay}/config/default-plugins.ts +0 -0
- /package/src/{saeeol → overlay}/config/markdown.ts +0 -0
- /package/src/{saeeol → overlay}/config-injector.ts +0 -0
- /package/src/{saeeol → overlay}/config-validation.ts +0 -0
- /package/src/{saeeol → overlay}/const.ts +0 -0
- /package/src/{saeeol → overlay}/cost-tracker/format.ts +0 -0
- /package/src/{saeeol → overlay}/cost-tracker/index.ts +0 -0
- /package/src/{saeeol → overlay}/cost-tracker/state.ts +0 -0
- /package/src/{saeeol → overlay}/cost-tracker/types.ts +0 -0
- /package/src/{saeeol → overlay}/docs/migration.md +0 -0
- /package/src/{saeeol → overlay}/docs/rules-migration.md +0 -0
- /package/src/{saeeol → overlay}/editor-context.ts +0 -0
- /package/src/{saeeol → overlay}/enhance-prompt.ts +0 -0
- /package/src/{saeeol → overlay}/errors.ts +0 -0
- /package/src/{saeeol → overlay}/generate-cli-docs.ts +0 -0
- /package/src/{saeeol → overlay}/help-command.ts +0 -0
- /package/src/{saeeol → overlay}/help.ts +0 -0
- /package/src/{saeeol → overlay}/i18n/index.ts +0 -0
- /package/src/{saeeol → overlay}/ignore-migrator.ts +0 -0
- /package/src/{saeeol → overlay}/index.ts +0 -0
- /package/src/{saeeol → overlay}/indexing-auth.ts +0 -0
- /package/src/{saeeol → overlay}/indexing-feature.ts +0 -0
- /package/src/{saeeol → overlay}/indexing-helpers.ts +0 -0
- /package/src/{saeeol → overlay}/indexing-label.ts +0 -0
- /package/src/{saeeol → overlay}/indexing-state.ts +0 -0
- /package/src/{saeeol → overlay}/indexing-types.ts +0 -0
- /package/src/{saeeol → overlay}/indexing.ts +0 -0
- /package/src/{saeeol → overlay}/lancedb.ts +0 -0
- /package/src/{saeeol → overlay}/mcp-migrator.ts +0 -0
- /package/src/{saeeol → overlay}/mcp-oauth-callback.ts +0 -0
- /package/src/{saeeol → overlay}/memory/age.ts +0 -0
- /package/src/{saeeol → overlay}/memory/index.ts +0 -0
- /package/src/{saeeol → overlay}/memory/paths.ts +0 -0
- /package/src/{saeeol → overlay}/memory/scan.ts +0 -0
- /package/src/{saeeol → overlay}/memory/types.ts +0 -0
- /package/src/{saeeol → overlay}/model-match.ts +0 -0
- /package/src/{saeeol → overlay}/modes-migrator.ts +0 -0
- /package/src/{saeeol → overlay}/paths.ts +0 -0
- /package/src/{saeeol → overlay}/permission/config-paths.ts +0 -0
- /package/src/{saeeol → overlay}/permission/drain.ts +0 -0
- /package/src/{saeeol → overlay}/permission/external-directory.ts +0 -0
- /package/src/{saeeol → overlay}/permission/read.ts +0 -0
- /package/src/{saeeol → overlay}/permission/routes.ts +0 -0
- /package/src/{saeeol → overlay}/permission/rule.ts +0 -0
- /package/src/{saeeol → overlay}/plan-followup-handover.ts +0 -0
- /package/src/{saeeol → overlay}/plan-followup-runtime.ts +0 -0
- /package/src/{saeeol → overlay}/plan-followup-session.ts +0 -0
- /package/src/{saeeol → overlay}/plan-followup.ts +0 -0
- /package/src/{saeeol → overlay}/plugins/home-footer.tsx +0 -0
- /package/src/{saeeol → overlay}/plugins/home-news.tsx +0 -0
- /package/src/{saeeol → overlay}/plugins/home-onboarding.tsx +0 -0
- /package/src/{saeeol → overlay}/plugins/sidebar-footer.tsx +0 -0
- /package/src/{saeeol → overlay}/plugins/sidebar-pr.tsx +0 -0
- /package/src/{saeeol → overlay}/plugins/sidebar-usage.tsx +0 -0
- /package/src/{saeeol → overlay}/project-id.ts +0 -0
- /package/src/{saeeol → overlay}/provider/codex-refresh.ts +0 -0
- /package/src/{saeeol → overlay}/provider/provider.ts +0 -0
- /package/src/{saeeol → overlay}/provider-options.ts +0 -0
- /package/src/{saeeol → overlay}/question/index.ts +0 -0
- /package/src/{saeeol → overlay}/remote-tui.tsx +0 -0
- /package/src/{saeeol → overlay}/review/command.ts +0 -0
- /package/src/{saeeol → overlay}/review/diff.ts +0 -0
- /package/src/{saeeol → overlay}/review/prompt.ts +0 -0
- /package/src/{saeeol → overlay}/review/review.ts +0 -0
- /package/src/{saeeol → overlay}/review/types.ts +0 -0
- /package/src/{saeeol → overlay}/review/worktree-diff.ts +0 -0
- /package/src/{saeeol → overlay}/rules-migrator.ts +0 -0
- /package/src/{saeeol → overlay}/server/instance.ts +0 -0
- /package/src/{saeeol → overlay}/server/router.ts +0 -0
- /package/src/{saeeol → overlay}/server/routes/commit-message.ts +0 -0
- /package/src/{saeeol → overlay}/server/routes/indexing.ts +0 -0
- /package/src/{saeeol → overlay}/server/server.ts +0 -0
- /package/src/{saeeol → overlay}/session/compaction-chunks-core.ts +0 -0
- /package/src/{saeeol → overlay}/session/compaction-chunks-utils.ts +0 -0
- /package/src/{saeeol → overlay}/session/compaction-chunks.ts +0 -0
- /package/src/{saeeol → overlay}/session/compaction-payload-recovery.ts +0 -0
- /package/src/{saeeol → overlay}/session/cost-propagation.ts +0 -0
- /package/src/{saeeol → overlay}/session/digest-storage.ts +0 -0
- /package/src/{saeeol → overlay}/session/fork.ts +0 -0
- /package/src/{saeeol → overlay}/session/index.ts +0 -0
- /package/src/{saeeol → overlay}/session/instruction.ts +0 -0
- /package/src/{saeeol → overlay}/session/kg-compaction.ts +0 -0
- /package/src/{saeeol → overlay}/session/llm.ts +0 -0
- /package/src/{saeeol → overlay}/session/overflow.ts +0 -0
- /package/src/{saeeol → overlay}/session/platform.ts +0 -0
- /package/src/{saeeol → overlay}/session/processor.ts +0 -0
- /package/src/{saeeol → overlay}/session/prompt-context.ts +0 -0
- /package/src/{saeeol → overlay}/session/prompt-plan.ts +0 -0
- /package/src/{saeeol → overlay}/session/prompt-queue.ts +0 -0
- /package/src/{saeeol → overlay}/session/prompt.ts +0 -0
- /package/src/{saeeol → overlay}/session/queries.ts +0 -0
- /package/src/{saeeol → overlay}/session/tui-sync.ts +0 -0
- /package/src/{saeeol → overlay}/session-import/routes.ts +0 -0
- /package/src/{saeeol → overlay}/session-import/service.ts +0 -0
- /package/src/{saeeol → overlay}/session-import/types.ts +0 -0
- /package/src/{saeeol → overlay}/skills/builtin.ts +0 -0
- /package/src/{saeeol → overlay}/skills/config.md +0 -0
- /package/src/{saeeol → overlay}/snapshot/diff-full.ts +0 -0
- /package/src/{saeeol → overlay}/snapshot/index.ts +0 -0
- /package/src/{saeeol → overlay}/snapshot/track-hooks.ts +0 -0
- /package/src/{saeeol → overlay}/snapshot/track-types.ts +0 -0
- /package/src/{saeeol → overlay}/snapshot/track.ts +0 -0
- /package/src/{saeeol → overlay}/soul.txt +0 -0
- /package/src/{saeeol → overlay}/suggestion/index.ts +0 -0
- /package/src/{saeeol → overlay}/suggestion/routes.ts +0 -0
- /package/src/{saeeol → overlay}/suggestion/tool.ts +0 -0
- /package/src/{saeeol → overlay}/suggestion/tool.txt +0 -0
- /package/src/{saeeol → overlay}/suggestion/tui/bar.tsx +0 -0
- /package/src/{saeeol → overlay}/suggestion/tui/prompt.tsx +0 -0
- /package/src/{saeeol → overlay}/suggestion/tui/render.tsx +0 -0
- /package/src/{saeeol → overlay}/suggestion/tui/sync.ts +0 -0
- /package/src/{saeeol → overlay}/system-prompt.ts +0 -0
- /package/src/{saeeol → overlay}/todo-view.ts +0 -0
- /package/src/{saeeol → overlay}/tool/agent-manager.ts +0 -0
- /package/src/{saeeol → overlay}/tool/agent-manager.txt +0 -0
- /package/src/{saeeol → overlay}/tool/bash-security-patterns.ts +0 -0
- /package/src/{saeeol → overlay}/tool/bash-security.ts +0 -0
- /package/src/{saeeol → overlay}/tool/question.ts +0 -0
- /package/src/{saeeol → overlay}/tool/registry.ts +0 -0
- /package/src/{saeeol → overlay}/tool/semantic-search.ts +0 -0
- /package/src/{saeeol → overlay}/tool/semantic-search.txt +0 -0
- /package/src/{saeeol → overlay}/tool/task.ts +0 -0
- /package/src/{saeeol → overlay}/ts-check.ts +0 -0
- /package/src/{saeeol → overlay}/ts-client.ts +0 -0
- /package/src/{saeeol → overlay}/tui/diff.ts +0 -0
- /package/src/{saeeol → overlay}/util/url.ts +0 -0
- /package/src/{saeeol → overlay}/worker/index.ts +0 -0
- /package/src/{saeeol → overlay}/worker/pool.ts +0 -0
- /package/src/{saeeol → overlay}/worker/store.ts +0 -0
- /package/src/{saeeol → overlay}/worker/types.ts +0 -0
- /package/src/{saeeol → overlay}/workflows-migrator.ts +0 -0
- /package/src/{saeeol → overlay}/worktree-cleanup.ts +0 -0
- /package/src/{saeeol → overlay}/worktree-family.ts +0 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { Effect } from "effect"
|
|
2
|
+
import path from "path"
|
|
3
|
+
import { Flag } from "@saeeol/core/flag/flag"
|
|
4
|
+
import { PartID } from "../core/schema"
|
|
5
|
+
import { MessageV2 } from "../message/message-v2"
|
|
6
|
+
import * as Session from "../core/session"
|
|
7
|
+
import { InstanceState } from "@/effect/instance-state"
|
|
8
|
+
import CODE_SWITCH from "./code-switch.txt"
|
|
9
|
+
import type { PromptDeps } from "./prompt-types"
|
|
10
|
+
import * as LTM from "@/ltm"
|
|
11
|
+
|
|
12
|
+
const PLAN_REMINDER = `<system-reminder>
|
|
13
|
+
Plan mode is active. The user indicated that they do not want you to execute yet -- you MUST NOT make any edits (with the exception of the plan file mentioned below), run any non-readonly tools (including changing configs or making commits), or otherwise make any changes to the system. This supersedes any other instructions you have received.
|
|
14
|
+
|
|
15
|
+
## Plan File Info:
|
|
16
|
+
{{PLAN_INFO}}
|
|
17
|
+
You should build your plan incrementally by writing to or editing this file. NOTE that this is the only file you are allowed to edit -- you are only allowed to take READ-ONLY actions.
|
|
18
|
+
|
|
19
|
+
## Plan Workflow
|
|
20
|
+
|
|
21
|
+
### Phase 1: Initial Understanding
|
|
22
|
+
Goal: Gain a comprehensive understanding of the user's request by reading through code and asking them questions. Critical to In this phase you should only use the explore subagent type.
|
|
23
|
+
|
|
24
|
+
1. Focus on understanding the user's request and the code associated with their request
|
|
25
|
+
2. **Launch up to 3 explore agents IN PARALLEL** to efficiently explore the codebase.
|
|
26
|
+
3. After exploring the code, use the question tool to clarify ambiguities in the user request up front.
|
|
27
|
+
|
|
28
|
+
### Phase 2: Design
|
|
29
|
+
Goal: Design an implementation approach. Launch general agent(s) based on exploration results.
|
|
30
|
+
|
|
31
|
+
### Phase 3: Review
|
|
32
|
+
Goal: Review the plan(s) and ensure alignment with the user's intentions.
|
|
33
|
+
|
|
34
|
+
### Phase 4: Final Plan
|
|
35
|
+
Goal: Write your final plan to the plan file. Include recommended approach, critical file paths, and verification steps.
|
|
36
|
+
|
|
37
|
+
### Phase 5: Call plan_exit tool
|
|
38
|
+
At the end, call plan_exit to indicate you are done planning. Do NOT stop unless asking a question or calling plan_exit.
|
|
39
|
+
</system-reminder>`
|
|
40
|
+
|
|
41
|
+
export const insertReminders = (deps: PromptDeps, SaeeolSessionPrompt: any) =>
|
|
42
|
+
Effect.fn("SessionPrompt.insertReminders")(function* (input: {
|
|
43
|
+
messages: MessageV2.WithParts[]
|
|
44
|
+
agent: any
|
|
45
|
+
session: Session.Info
|
|
46
|
+
}) {
|
|
47
|
+
const userMessage = input.messages.findLast((msg) => msg.info.role === "user")
|
|
48
|
+
if (!userMessage) return input.messages
|
|
49
|
+
|
|
50
|
+
if (!Flag.SAEEOL_EXPERIMENTAL_PLAN_MODE) {
|
|
51
|
+
yield* Effect.promise(() =>
|
|
52
|
+
SaeeolSessionPrompt.insertPlanReminders({ agent: input.agent, session: input.session, userMessage }),
|
|
53
|
+
)
|
|
54
|
+
const wasPlan = input.messages.some((msg) => msg.info.role === "assistant" && msg.info.agent === "plan")
|
|
55
|
+
if (wasPlan && input.agent.name === "code") {
|
|
56
|
+
userMessage.parts.push({
|
|
57
|
+
id: PartID.ascending(), messageID: userMessage.info.id,
|
|
58
|
+
sessionID: userMessage.info.sessionID, type: "text", text: CODE_SWITCH, synthetic: true,
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// LTM retrieval — inject relevant long-term memories into the prompt
|
|
63
|
+
const cfg = yield* deps.config.get()
|
|
64
|
+
if (cfg?.ltm?.enabled) {
|
|
65
|
+
const userText = userMessage.parts
|
|
66
|
+
.filter((p) => p.type === "text")
|
|
67
|
+
.map((p) => (p as any).text ?? "")
|
|
68
|
+
.join(" ")
|
|
69
|
+
.slice(0, 500)
|
|
70
|
+
if (userText.length > 10) {
|
|
71
|
+
const ltmCfg = {
|
|
72
|
+
...LTM.Config.DEFAULT_LTM_CONFIG,
|
|
73
|
+
...cfg.ltm,
|
|
74
|
+
episodic: { ...LTM.Config.DEFAULT_LTM_CONFIG.episodic, ...cfg.ltm.episodic },
|
|
75
|
+
semantic: { ...LTM.Config.DEFAULT_LTM_CONFIG.semantic, ...cfg.ltm.semantic },
|
|
76
|
+
procedural: { ...LTM.Config.DEFAULT_LTM_CONFIG.procedural, ...cfg.ltm.procedural },
|
|
77
|
+
retrieval: { ...LTM.Config.DEFAULT_LTM_CONFIG.retrieval, ...cfg.ltm.retrieval },
|
|
78
|
+
}
|
|
79
|
+
const context = yield* Effect.promise(() => LTM.Retrieval.inject(userText, ltmCfg))
|
|
80
|
+
if (context) {
|
|
81
|
+
userMessage.parts.push({
|
|
82
|
+
id: PartID.ascending(), messageID: userMessage.info.id,
|
|
83
|
+
sessionID: userMessage.info.sessionID, type: "text", text: `\n${context}`, synthetic: true,
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return input.messages
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const assistantMessage = input.messages.findLast((msg) => msg.info.role === "assistant")
|
|
93
|
+
if (input.agent.name !== "plan" && assistantMessage?.info.agent === "plan") {
|
|
94
|
+
const ctx = yield* InstanceState.context
|
|
95
|
+
const plan = Session.plan(input.session, ctx)
|
|
96
|
+
if (!(yield* deps.fsys.existsSafe(plan))) return input.messages
|
|
97
|
+
const part = yield* deps.sessions.updatePart({
|
|
98
|
+
id: PartID.ascending(), messageID: userMessage.info.id, sessionID: userMessage.info.sessionID,
|
|
99
|
+
type: "text", text: `${CODE_SWITCH}\n\nA plan file exists at ${plan}. You should execute on the plan defined within it`, synthetic: true,
|
|
100
|
+
})
|
|
101
|
+
userMessage.parts.push(part)
|
|
102
|
+
return input.messages
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (input.agent.name !== "plan" || assistantMessage?.info.agent === "plan") return input.messages
|
|
106
|
+
|
|
107
|
+
const ctx = yield* InstanceState.context
|
|
108
|
+
const plan = Session.plan(input.session, ctx)
|
|
109
|
+
const exists = yield* deps.fsys.existsSafe(plan)
|
|
110
|
+
if (!exists) yield* deps.fsys.ensureDir(path.dirname(plan)).pipe(Effect.catch(Effect.die))
|
|
111
|
+
const planInfo = exists
|
|
112
|
+
? `A plan file already exists at ${plan}. You can read it and make incremental edits using the edit tool.`
|
|
113
|
+
: `No plan file exists yet. You should create your plan at ${plan} using the write tool.`
|
|
114
|
+
const part = yield* deps.sessions.updatePart({
|
|
115
|
+
id: PartID.ascending(), messageID: userMessage.info.id, sessionID: userMessage.info.sessionID,
|
|
116
|
+
type: "text", text: PLAN_REMINDER.replace("{{PLAN_INFO}}", planInfo), synthetic: true,
|
|
117
|
+
})
|
|
118
|
+
userMessage.parts.push(part)
|
|
119
|
+
return input.messages
|
|
120
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Effect, Types, Option } from "effect"
|
|
2
|
+
import path from "path"
|
|
3
|
+
import os from "os"
|
|
4
|
+
import { ConfigMarkdown } from "@/config/markdown"
|
|
5
|
+
import { pathToFileURL } from "url"
|
|
6
|
+
import { InstanceState } from "@/effect/instance-state"
|
|
7
|
+
import type { PromptInput } from "./prompt-schemas"
|
|
8
|
+
import type { PromptDeps } from "./prompt-types"
|
|
9
|
+
|
|
10
|
+
export const resolvePromptParts = (deps: PromptDeps) =>
|
|
11
|
+
Effect.fn("SessionPrompt.resolvePromptParts")(function* (template: string) {
|
|
12
|
+
const ctx = yield* InstanceState.context
|
|
13
|
+
const parts: Types.DeepMutable<PromptInput["parts"]> = [{ type: "text", text: template }]
|
|
14
|
+
const files = ConfigMarkdown.files(template)
|
|
15
|
+
const seen = new Set<string>()
|
|
16
|
+
yield* Effect.forEach(
|
|
17
|
+
files,
|
|
18
|
+
Effect.fnUntraced(function* (match: RegExpExecArray) {
|
|
19
|
+
const name = match[1]
|
|
20
|
+
if (seen.has(name)) return
|
|
21
|
+
seen.add(name)
|
|
22
|
+
const filepath = name.startsWith("~/")
|
|
23
|
+
? path.join(os.homedir(), name.slice(2))
|
|
24
|
+
: path.resolve(ctx.worktree, name)
|
|
25
|
+
const info = yield* deps.fsys.stat(filepath).pipe(Effect.option)
|
|
26
|
+
if (Option.isNone(info)) {
|
|
27
|
+
const found = yield* deps.agents.get(name)
|
|
28
|
+
if (found) parts.push({ type: "agent", name: found.name })
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
const stat = info.value
|
|
32
|
+
parts.push({
|
|
33
|
+
type: "file",
|
|
34
|
+
url: pathToFileURL(filepath).href,
|
|
35
|
+
filename: name,
|
|
36
|
+
mime: stat.type === "Directory" ? "application/x-directory" : "text/plain",
|
|
37
|
+
})
|
|
38
|
+
}),
|
|
39
|
+
{ concurrency: "unbounded", discard: true },
|
|
40
|
+
)
|
|
41
|
+
return parts
|
|
42
|
+
})
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import z from "zod"
|
|
2
|
+
import { SessionID, MessageID, PartID } from "../core/schema"
|
|
3
|
+
import { MessageV2 } from "../message/message-v2"
|
|
4
|
+
import { ModelID, ProviderID } from "../../provider/schema"
|
|
5
|
+
import { type Tool as AITool, tool, jsonSchema } from "ai"
|
|
6
|
+
import type { JSONSchema7 } from "@ai-sdk/provider"
|
|
7
|
+
import { Schema } from "effect"
|
|
8
|
+
import { zod } from "@/util/effect-zod"
|
|
9
|
+
import { withStatics } from "@/util/schema"
|
|
10
|
+
|
|
11
|
+
export const STRUCTURED_OUTPUT_DESCRIPTION = `Use this tool to return your final response in the requested structured format.
|
|
12
|
+
|
|
13
|
+
IMPORTANT:
|
|
14
|
+
- You MUST call this tool exactly once at the end of your response
|
|
15
|
+
- The input must be valid JSON matching the required schema
|
|
16
|
+
- Complete all necessary research and tool calls BEFORE calling this tool
|
|
17
|
+
- This tool provides your final answer - no further actions are taken after calling it`
|
|
18
|
+
|
|
19
|
+
export const STRUCTURED_OUTPUT_SYSTEM_PROMPT = `IMPORTANT: The user has requested structured output. You MUST use the StructuredOutput tool to provide your final response. Do NOT respond with plain text - you MUST call the StructuredOutput tool with your answer formatted according to the schema.`
|
|
20
|
+
|
|
21
|
+
export const REQUEST_PRUNE_BYTES = 1_250_000
|
|
22
|
+
|
|
23
|
+
const ModelRef = Schema.Struct({
|
|
24
|
+
providerID: ProviderID,
|
|
25
|
+
modelID: ModelID,
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
export const PromptInput = Schema.Struct({
|
|
29
|
+
sessionID: SessionID,
|
|
30
|
+
messageID: Schema.optional(MessageID),
|
|
31
|
+
model: Schema.optional(ModelRef),
|
|
32
|
+
agent: Schema.optional(Schema.String),
|
|
33
|
+
noReply: Schema.optional(Schema.Boolean),
|
|
34
|
+
tools: Schema.optional(Schema.Record(Schema.String, Schema.Boolean)).annotate({
|
|
35
|
+
description:
|
|
36
|
+
"@deprecated tools and permissions have been merged, you can set permissions on the session itself now",
|
|
37
|
+
}),
|
|
38
|
+
format: Schema.optional(MessageV2.Format),
|
|
39
|
+
system: Schema.optional(Schema.String),
|
|
40
|
+
variant: Schema.optional(Schema.String),
|
|
41
|
+
editorContext: Schema.optional(MessageV2.EditorContext),
|
|
42
|
+
parts: Schema.Array(
|
|
43
|
+
Schema.Union([
|
|
44
|
+
MessageV2.TextPartInput,
|
|
45
|
+
MessageV2.FilePartInput,
|
|
46
|
+
MessageV2.AgentPartInput,
|
|
47
|
+
MessageV2.SubtaskPartInput,
|
|
48
|
+
]).annotate({ discriminator: "type" }),
|
|
49
|
+
),
|
|
50
|
+
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
|
51
|
+
|
|
52
|
+
type PartInputUnion =
|
|
53
|
+
| MessageV2.TextPartInput
|
|
54
|
+
| MessageV2.FilePartInput
|
|
55
|
+
| MessageV2.AgentPartInput
|
|
56
|
+
| MessageV2.SubtaskPartInput
|
|
57
|
+
export type PromptInput = Omit<Schema.Schema.Type<typeof PromptInput>, "parts" | "editorContext"> & {
|
|
58
|
+
parts: PartInputUnion[]
|
|
59
|
+
editorContext?: MessageV2.EditorContext
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export class LoopInput extends Schema.Class<LoopInput>("SessionPrompt.LoopInput")({
|
|
63
|
+
sessionID: SessionID,
|
|
64
|
+
}) {
|
|
65
|
+
static readonly zod = zod(this)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export const ShellInput = Schema.Struct({
|
|
69
|
+
sessionID: SessionID,
|
|
70
|
+
messageID: Schema.optional(MessageID),
|
|
71
|
+
agent: Schema.String,
|
|
72
|
+
model: Schema.optional(ModelRef),
|
|
73
|
+
command: Schema.String,
|
|
74
|
+
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
|
75
|
+
export type ShellInput = Schema.Schema.Type<typeof ShellInput>
|
|
76
|
+
|
|
77
|
+
export const CommandInput = Schema.Struct({
|
|
78
|
+
messageID: Schema.optional(MessageID),
|
|
79
|
+
sessionID: SessionID,
|
|
80
|
+
agent: Schema.optional(Schema.String),
|
|
81
|
+
model: Schema.optional(Schema.String),
|
|
82
|
+
arguments: Schema.String,
|
|
83
|
+
command: Schema.String,
|
|
84
|
+
variant: Schema.optional(Schema.String),
|
|
85
|
+
parts: Schema.optional(
|
|
86
|
+
Schema.Array(
|
|
87
|
+
Schema.Union([
|
|
88
|
+
Schema.Struct({
|
|
89
|
+
id: Schema.optional(PartID),
|
|
90
|
+
type: Schema.Literal("file"),
|
|
91
|
+
mime: Schema.String,
|
|
92
|
+
filename: Schema.optional(Schema.String),
|
|
93
|
+
url: Schema.String,
|
|
94
|
+
source: Schema.optional(MessageV2.FilePartSource),
|
|
95
|
+
}),
|
|
96
|
+
]).annotate({ discriminator: "type" }),
|
|
97
|
+
),
|
|
98
|
+
),
|
|
99
|
+
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
|
100
|
+
export type CommandInput = Schema.Schema.Type<typeof CommandInput>
|
|
101
|
+
|
|
102
|
+
export const bashRegex = /!`([^`]+)`/g
|
|
103
|
+
export const argsRegex = /(?:\[Image\s+\d+\]|"[^"]*"|'[^']*'|[^\s"']+)/gi
|
|
104
|
+
export const placeholderRegex = /\$(\d+)/g
|
|
105
|
+
export const quoteTrimRegex = /^["']|["']$/g
|
|
106
|
+
|
|
107
|
+
/** @internal Exported for testing */
|
|
108
|
+
export function createStructuredOutputTool(input: {
|
|
109
|
+
schema: Record<string, any>
|
|
110
|
+
onSuccess: (output: unknown) => void
|
|
111
|
+
}): AITool {
|
|
112
|
+
const { $schema: _, ...toolSchema } = input.schema
|
|
113
|
+
return tool({
|
|
114
|
+
description: STRUCTURED_OUTPUT_DESCRIPTION,
|
|
115
|
+
inputSchema: jsonSchema(toolSchema as JSONSchema7),
|
|
116
|
+
async execute(args) {
|
|
117
|
+
input.onSuccess(args)
|
|
118
|
+
return {
|
|
119
|
+
output: "Structured output captured successfully.",
|
|
120
|
+
title: "Structured Output",
|
|
121
|
+
metadata: { valid: true },
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
toModelOutput({ output }) {
|
|
125
|
+
return { type: "text", value: output.output }
|
|
126
|
+
},
|
|
127
|
+
})
|
|
128
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Effect, Cause, Stream } from "effect"
|
|
2
|
+
import * as Log from "@saeeol/core/util/log"
|
|
3
|
+
import * as EffectLogger from "@saeeol/core/effect/logger"
|
|
4
|
+
import * as Session from "../core/session"
|
|
5
|
+
import { MessageV2 } from "../message/message-v2"
|
|
6
|
+
import type { PromptDeps } from "./prompt-types"
|
|
7
|
+
|
|
8
|
+
const elog = EffectLogger.create({ service: "session.prompt" })
|
|
9
|
+
|
|
10
|
+
export const ensureTitle = (deps: PromptDeps) =>
|
|
11
|
+
Effect.fn("SessionPrompt.ensureTitle")(function* (input: {
|
|
12
|
+
session: Session.Info
|
|
13
|
+
history: MessageV2.WithParts[]
|
|
14
|
+
providerID: any
|
|
15
|
+
modelID: any
|
|
16
|
+
}) {
|
|
17
|
+
if (input.session.parentID) return
|
|
18
|
+
if (!Session.isDefaultTitle(input.session.title)) return
|
|
19
|
+
const real = (m: MessageV2.WithParts) =>
|
|
20
|
+
m.info.role === "user" && !m.parts.every((p) => "synthetic" in p && p.synthetic)
|
|
21
|
+
const idx = input.history.findIndex(real)
|
|
22
|
+
if (idx === -1) return
|
|
23
|
+
if (input.history.filter(real).length !== 1) return
|
|
24
|
+
const context = input.history.slice(0, idx + 1)
|
|
25
|
+
const firstUser = context[idx]
|
|
26
|
+
if (!firstUser || firstUser.info.role !== "user") return
|
|
27
|
+
const firstInfo = firstUser.info
|
|
28
|
+
const subtasks = firstUser.parts.filter((p): p is MessageV2.SubtaskPart => p.type === "subtask")
|
|
29
|
+
const onlySubtasks = subtasks.length > 0 && firstUser.parts.every((p) => p.type === "subtask")
|
|
30
|
+
const ag = yield* deps.agents.get("title")
|
|
31
|
+
if (!ag) return
|
|
32
|
+
const mdl = ag.model
|
|
33
|
+
? yield* deps.provider.getModel(ag.model.providerID, ag.model.modelID)
|
|
34
|
+
: ((yield* deps.provider.getSmallModel(input.providerID)) ??
|
|
35
|
+
(yield* deps.provider.getModel(input.providerID, input.modelID)))
|
|
36
|
+
const msgs = onlySubtasks
|
|
37
|
+
? [{ role: "user" as const, content: subtasks.map((p) => p.prompt).join("\n") }]
|
|
38
|
+
: yield* MessageV2.toModelMessagesEffect(context, mdl)
|
|
39
|
+
const text = yield* deps.llm.stream({
|
|
40
|
+
agent: ag, user: firstInfo, system: [], small: true, tools: {}, model: mdl,
|
|
41
|
+
sessionID: input.session.id, retries: 2,
|
|
42
|
+
messages: [{ role: "user", content: "Generate a title for this conversation:\n" }, ...msgs],
|
|
43
|
+
}).pipe(
|
|
44
|
+
Stream.filter((e: any): e is Extract<any, { type: "text-delta" }> => e.type === "text-delta"),
|
|
45
|
+
Stream.map((e: any) => e.text),
|
|
46
|
+
Stream.mkString,
|
|
47
|
+
Effect.orDie,
|
|
48
|
+
)
|
|
49
|
+
const cleaned = text.replace(/<think[\s\S]*?<\/think>\s*/g, "")
|
|
50
|
+
.split("\n").map((l: string) => l.trim()).find((l: string) => l.length > 0)
|
|
51
|
+
if (!cleaned) return
|
|
52
|
+
const t = cleaned.length > 100 ? cleaned.substring(0, 97) + "..." : cleaned
|
|
53
|
+
yield* deps.sessions.setTitle({ sessionID: input.session.id, title: t })
|
|
54
|
+
.pipe(Effect.catchCause((cause) => elog.error("failed to generate title", { error: Cause.squash(cause) })))
|
|
55
|
+
})
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { Effect, Context, Types, Option, Scope, Exit, Cause, Latch, Layer } from "effect"
|
|
2
|
+
import { SessionID, MessageID, PartID } from "../core/schema"
|
|
3
|
+
import { MessageV2 } from "../message/message-v2"
|
|
4
|
+
import type { PromptInput, ShellInput, CommandInput, LoopInput } from "./prompt-schemas"
|
|
5
|
+
import type { ModelID, ProviderID } from "../../provider/schema"
|
|
6
|
+
|
|
7
|
+
export interface Interface {
|
|
8
|
+
readonly cancel: (sessionID: SessionID) => Effect.Effect<void>
|
|
9
|
+
readonly prompt: (input: PromptInput) => Effect.Effect<MessageV2.WithParts>
|
|
10
|
+
readonly loop: (input: LoopInput) => Effect.Effect<MessageV2.WithParts>
|
|
11
|
+
readonly shell: (input: ShellInput) => Effect.Effect<MessageV2.WithParts>
|
|
12
|
+
readonly command: (input: CommandInput) => Effect.Effect<MessageV2.WithParts>
|
|
13
|
+
readonly resolvePromptParts: (template: string) => Effect.Effect<PromptInput["parts"]>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class Service extends Context.Service<Service, Interface>()("@saeeol/SessionPrompt") {}
|
|
17
|
+
|
|
18
|
+
export interface PromptDeps {
|
|
19
|
+
bus: any
|
|
20
|
+
status: any
|
|
21
|
+
sessions: any
|
|
22
|
+
agents: any
|
|
23
|
+
provider: any
|
|
24
|
+
processor: any
|
|
25
|
+
compaction: any
|
|
26
|
+
plugin: any
|
|
27
|
+
commands: any
|
|
28
|
+
config: any
|
|
29
|
+
permission: any
|
|
30
|
+
fsys: any
|
|
31
|
+
mcp: any
|
|
32
|
+
lsp: any
|
|
33
|
+
registry: any
|
|
34
|
+
truncate: any
|
|
35
|
+
spawner: any
|
|
36
|
+
scope: Scope.Scope
|
|
37
|
+
instruction: any
|
|
38
|
+
state: any
|
|
39
|
+
revert: any
|
|
40
|
+
summary: any
|
|
41
|
+
sys: any
|
|
42
|
+
llm: any
|
|
43
|
+
resolveToolsSvc: any
|
|
44
|
+
userPartSvc: any
|
|
45
|
+
subtaskSvc: any
|
|
46
|
+
shellSvc: any
|
|
47
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Effect, Types } from "effect"
|
|
2
|
+
import { MessageID, PartID } from "../core/schema"
|
|
3
|
+
import { MessageV2 } from "../message/message-v2"
|
|
4
|
+
import { NamedError } from "@saeeol/core/util/error"
|
|
5
|
+
import * as Log from "@saeeol/core/util/log"
|
|
6
|
+
import type { PromptInput } from "./prompt-schemas"
|
|
7
|
+
import type { PromptDeps } from "./prompt-types"
|
|
8
|
+
import { getModel, lastModel } from "./prompt-model"
|
|
9
|
+
|
|
10
|
+
const log = Log.create({ service: "session.prompt" })
|
|
11
|
+
|
|
12
|
+
export const createUserMessage = (deps: PromptDeps) =>
|
|
13
|
+
Effect.fn("SessionPrompt.createUserMessage")(function* (input: PromptInput) {
|
|
14
|
+
const agentName = input.agent || (yield* deps.agents.defaultAgent())
|
|
15
|
+
const ag = yield* deps.agents.get(agentName)
|
|
16
|
+
if (!ag) {
|
|
17
|
+
const available = (yield* deps.agents.list()).filter((a: any) => !a.hidden).map((a: any) => a.name)
|
|
18
|
+
const hint = available.length ? ` Available agents: ${available.join(", ")}` : ""
|
|
19
|
+
const error = new NamedError.Unknown({ message: `Agent not found: "${agentName}".${hint}` })
|
|
20
|
+
yield* deps.bus.publish(deps.sessions.Event?.Error ?? { type: "session.error" }, { sessionID: input.sessionID, error: error.toObject() })
|
|
21
|
+
throw error
|
|
22
|
+
}
|
|
23
|
+
const model = input.model ?? ag.model ?? (yield* lastModel(deps)(input.sessionID))
|
|
24
|
+
const same = ag.model && model.providerID === ag.model.providerID && model.modelID === ag.model.modelID
|
|
25
|
+
const full = !input.variant && ag.variant && same
|
|
26
|
+
? yield* deps.provider.getModel(model.providerID, model.modelID).pipe(Effect.catchDefect(() => Effect.void))
|
|
27
|
+
: undefined
|
|
28
|
+
const variant = input.variant ?? (ag.variant && full?.variants?.[ag.variant] ? ag.variant : undefined)
|
|
29
|
+
const info: MessageV2.User = {
|
|
30
|
+
id: input.messageID ?? MessageID.ascending(),
|
|
31
|
+
role: "user",
|
|
32
|
+
sessionID: input.sessionID,
|
|
33
|
+
time: { created: Date.now() },
|
|
34
|
+
tools: input.tools,
|
|
35
|
+
agent: ag.name,
|
|
36
|
+
model: { providerID: model.providerID, modelID: model.modelID, variant },
|
|
37
|
+
system: input.system,
|
|
38
|
+
format: input.format,
|
|
39
|
+
editorContext: input.editorContext,
|
|
40
|
+
}
|
|
41
|
+
yield* Effect.addFinalizer(() => deps.instruction.clear(info.id))
|
|
42
|
+
type Draft<T> = T extends MessageV2.Part ? Omit<T, "id"> & { id?: string } : never
|
|
43
|
+
const assign = (part: Draft<MessageV2.Part>): MessageV2.Part => ({
|
|
44
|
+
...part,
|
|
45
|
+
id: part.id ? PartID.make(part.id) : PartID.ascending(),
|
|
46
|
+
})
|
|
47
|
+
const resolvePart = (part: PromptInput["parts"][number]) =>
|
|
48
|
+
deps.userPartSvc.resolve(part, {
|
|
49
|
+
sessionID: input.sessionID,
|
|
50
|
+
messageID: info.id,
|
|
51
|
+
agent: input.agent!,
|
|
52
|
+
agentPermission: ag.permission,
|
|
53
|
+
model: info.model,
|
|
54
|
+
})
|
|
55
|
+
const parts = yield* Effect.forEach(input.parts, resolvePart, { concurrency: "unbounded" }).pipe(
|
|
56
|
+
Effect.map((x: any) => x.flat().map(assign)),
|
|
57
|
+
)
|
|
58
|
+
yield* deps.plugin.trigger("chat.message", {
|
|
59
|
+
sessionID: input.sessionID, agent: input.agent, model: input.model,
|
|
60
|
+
messageID: input.messageID, variant: input.variant,
|
|
61
|
+
}, { message: info, parts })
|
|
62
|
+
const parsed = (MessageV2 as any).Info?.zod?.safeParse?.(info) ?? { success: true }
|
|
63
|
+
if (!parsed.success) {
|
|
64
|
+
log.error("invalid user message before save", {
|
|
65
|
+
sessionID: input.sessionID, messageID: info.id, agent: info.agent,
|
|
66
|
+
model: info.model, issues: parsed.error?.issues,
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
parts.forEach((part: any, index: number) => {
|
|
70
|
+
const p = (MessageV2 as any).Part?.zod?.safeParse?.(part) ?? { success: true }
|
|
71
|
+
if (p.success) return
|
|
72
|
+
log.error("invalid user part before save", {
|
|
73
|
+
sessionID: input.sessionID, messageID: info.id, partID: part.id,
|
|
74
|
+
partType: part.type, index, issues: p.error?.issues, part,
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
yield* deps.sessions.updateMessage(info)
|
|
78
|
+
for (const part of parts) yield* deps.sessions.updatePart(part)
|
|
79
|
+
return { info, parts }
|
|
80
|
+
}, Effect.scoped)
|