saeeol 1.2.5 → 1.2.8
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 +17 -12
- package/src/ltm/config.ts +15 -15
- package/src/ltm/events.ts +1 -1
- package/src/ltm/index.ts +1 -1
- package/src/ltm/pipeline.ts +22 -22
- package/src/ltm/scheduler.ts +20 -20
- package/src/ltm/store.ts +9 -7
- package/src/ltm/types.ts +16 -16
- package/src/provider/local/embedder.ts +21 -21
- package/src/provider/models-snapshot.d.ts +2 -0
- package/src/provider/models-snapshot.js +3 -0
- package/src/session/core/session.ts +1 -39
- package/src/session/message/message-errors.ts +1 -1
- package/src/session/message/message-parts.ts +1 -1
- package/src/session/message/message-transform.ts +1 -1
- package/src/session/message/message-types.ts +1 -1
- package/src/tool/core/tool.ts +1 -1
- package/AGENTS.md +0 -72
- package/BUN_SHELL_MIGRATION_PLAN.md +0 -136
- package/Dockerfile +0 -18
- package/assets/saeeol.ico +0 -0
- package/bunfig.toml +0 -7
- package/database.db +0 -0
- package/drizzle.config.ts +0 -10
- package/git +0 -0
- package/migration/20260127222353_familiar_lady_ursula/migration.sql +0 -90
- package/migration/20260127222353_familiar_lady_ursula/snapshot.json +0 -796
- package/migration/20260211171708_add_project_commands/migration.sql +0 -1
- package/migration/20260211171708_add_project_commands/snapshot.json +0 -806
- package/migration/20260213144116_wakeful_the_professor/migration.sql +0 -11
- package/migration/20260213144116_wakeful_the_professor/snapshot.json +0 -897
- package/migration/20260225215848_workspace/migration.sql +0 -7
- package/migration/20260225215848_workspace/snapshot.json +0 -959
- package/migration/20260227213759_add_session_workspace_id/migration.sql +0 -2
- package/migration/20260227213759_add_session_workspace_id/snapshot.json +0 -983
- package/migration/20260228203230_blue_harpoon/migration.sql +0 -17
- package/migration/20260228203230_blue_harpoon/snapshot.json +0 -1102
- package/migration/20260303231226_add_workspace_fields/migration.sql +0 -5
- package/migration/20260303231226_add_workspace_fields/snapshot.json +0 -1013
- package/migration/20260309230000_move_org_to_state/migration.sql +0 -3
- package/migration/20260309230000_move_org_to_state/snapshot.json +0 -1156
- package/migration/20260312043431_session_message_cursor/migration.sql +0 -4
- package/migration/20260312043431_session_message_cursor/snapshot.json +0 -1168
- package/migration/20260323234822_events/migration.sql +0 -13
- package/migration/20260323234822_events/snapshot.json +0 -1271
- package/migration/20260410174513_workspace-name/migration.sql +0 -16
- package/migration/20260410174513_workspace-name/snapshot.json +0 -1271
- package/migration/20260413175956_chief_energizer/migration.sql +0 -13
- package/migration/20260413175956_chief_energizer/snapshot.json +0 -1399
- package/migration/20260423070820_add_icon_url_override/migration.sql +0 -2
- package/migration/20260423070820_add_icon_url_override/snapshot.json +0 -1409
- package/migration/20260428004200_add_session_path/migration.sql +0 -1
- package/migration/20260428004200_add_session_path/snapshot.json +0 -1419
- package/npm/bin/saeeol +0 -42
- package/npm/package.json +0 -39
- package/npm/postinstall.js +0 -162
- package/parsers-config.ts +0 -289
- package/script/build.ts +0 -393
- package/script/check-migrations.ts +0 -16
- package/script/fix-node-pty.ts +0 -34
- package/script/generate.ts +0 -23
- package/script/postinstall.mjs +0 -189
- package/script/publish.ts +0 -200
- package/script/run-workspace-server +0 -106
- package/script/schema.ts +0 -63
- package/script/test-runner.ts +0 -420
- package/script/time.ts +0 -6
- package/script/trace-imports.ts +0 -153
- package/script/upgrade-opentui.ts +0 -64
- package/scripts/diff-sdk-types.sh +0 -52
- package/specs/effect/facades.md +0 -221
- package/specs/effect/http-api.md +0 -401
- package/specs/effect/instance-context.md +0 -309
- package/specs/effect/loose-ends.md +0 -34
- package/specs/effect/migration.md +0 -299
- package/specs/effect/routes.md +0 -64
- package/specs/effect/schema.md +0 -399
- package/specs/effect/server-package.md +0 -668
- package/specs/effect/tools.md +0 -90
- package/specs/tui-plugins.md +0 -433
- package/specs/v2/api.ts +0 -67
- package/specs/v2/keymappings.md +0 -10
- package/specs/v2/message-shape.md +0 -136
- package/src/tool/apply_patch.txt +0 -33
- package/src/tool/bash.txt +0 -119
- package/src/tool/edit.txt +0 -10
- package/src/tool/glob.txt +0 -6
- package/src/tool/grep.txt +0 -8
- package/src/tool/lsp.txt +0 -24
- package/src/tool/plan-enter.txt +0 -14
- package/src/tool/plan-exit.txt +0 -13
- package/src/tool/question.txt +0 -11
- package/src/tool/read.txt +0 -14
- package/src/tool/recall.txt +0 -12
- package/src/tool/skill.txt +0 -5
- package/src/tool/task.txt +0 -57
- package/src/tool/todowrite.txt +0 -167
- package/src/tool/warpgrep.txt +0 -10
- package/src/tool/webfetch.txt +0 -13
- package/src/tool/websearch.txt +0 -14
- package/src/tool/write.txt +0 -8
- package/sst-env.d.ts +0 -10
- package/test/AGENTS.md +0 -133
- package/test/account/repo.test.ts +0 -352
- package/test/account/service.test.ts +0 -456
- package/test/acp/agent-interface.test.ts +0 -51
- package/test/acp/event-subscription.test.ts +0 -725
- package/test/agent/agent.test.ts +0 -890
- package/test/auth/auth.test.ts +0 -86
- package/test/bun/registry.test.ts +0 -75
- package/test/bus/bus-effect.test.ts +0 -161
- package/test/bus/bus-integration.test.ts +0 -87
- package/test/bus/bus.test.ts +0 -219
- package/test/cli/account.test.ts +0 -26
- package/test/cli/auto-mode.test.ts +0 -75
- package/test/cli/bin-saeeol.test.ts +0 -8
- package/test/cli/cmd/tui/prompt-part.test.ts +0 -47
- package/test/cli/cmd/tui/prompt-traits.test.ts +0 -38
- package/test/cli/cmd/tui/sync.test.tsx +0 -159
- package/test/cli/error.test.ts +0 -18
- package/test/cli/github-action.test.ts +0 -198
- package/test/cli/github-remote.test.ts +0 -85
- package/test/cli/import.test.ts +0 -97
- package/test/cli/install-artifact.test.ts +0 -72
- package/test/cli/plugin-auth-picker.test.ts +0 -120
- package/test/cli/pr.test.ts +0 -59
- package/test/cli/tui/editor-context-zed.test.ts +0 -356
- package/test/cli/tui/editor-context.test.tsx +0 -228
- package/test/cli/tui/keybind-plugin.test.ts +0 -90
- package/test/cli/tui/markdown.test.ts +0 -161
- package/test/cli/tui/plugin-add.test.ts +0 -111
- package/test/cli/tui/plugin-install.test.ts +0 -87
- package/test/cli/tui/plugin-lifecycle.test.ts +0 -224
- package/test/cli/tui/plugin-loader-entrypoint.test.ts +0 -484
- package/test/cli/tui/plugin-loader-pure.test.ts +0 -71
- package/test/cli/tui/plugin-loader.test.ts +0 -816
- package/test/cli/tui/plugin-toggle.test.ts +0 -157
- package/test/cli/tui/revert-diff.test.ts +0 -35
- package/test/cli/tui/slot-replace.test.tsx +0 -47
- package/test/cli/tui/theme-store.test.ts +0 -54
- package/test/cli/tui/thread.test.ts +0 -28
- package/test/cli/tui/transcript.test.ts +0 -426
- package/test/cli/tui/usage.test.ts +0 -60
- package/test/cli/tui/use-event.test.tsx +0 -175
- package/test/config/agent-color.test.ts +0 -67
- package/test/config/config.test.ts +0 -2544
- package/test/config/fixtures/empty-frontmatter.md +0 -4
- package/test/config/fixtures/frontmatter.md +0 -28
- package/test/config/fixtures/markdown-header.md +0 -11
- package/test/config/fixtures/no-frontmatter.md +0 -1
- package/test/config/fixtures/weird-model-id.md +0 -13
- package/test/config/lsp.test.ts +0 -87
- package/test/config/markdown.test.ts +0 -228
- package/test/config/plugin.test.ts +0 -0
- package/test/config/tui.test.ts +0 -624
- package/test/control-plane/adapters.test.ts +0 -71
- package/test/control-plane/workspace.test.ts +0 -1526
- package/test/effect/app-runtime-logger.test.ts +0 -98
- package/test/effect/config-service.test.ts +0 -65
- package/test/effect/instance-state.test.ts +0 -394
- package/test/effect/run-service.test.ts +0 -89
- package/test/effect/runner.test.ts +0 -523
- package/test/fake/provider.ts +0 -82
- package/test/file/fsmonitor.test.ts +0 -68
- package/test/file/ignore.test.ts +0 -10
- package/test/file/index.test.ts +0 -954
- package/test/file/path-traversal.test.ts +0 -205
- package/test/file/ripgrep.test.ts +0 -226
- package/test/file/watcher.test.ts +0 -249
- package/test/filesystem/filesystem.test.ts +0 -319
- package/test/fixture/db.ts +0 -11
- package/test/fixture/fixture.test.ts +0 -26
- package/test/fixture/fixture.ts +0 -175
- package/test/fixture/flock-worker.ts +0 -72
- package/test/fixture/log-init-worker.ts +0 -62
- package/test/fixture/lsp/fake-lsp-server.js +0 -249
- package/test/fixture/plug-worker.ts +0 -93
- package/test/fixture/plugin-meta-worker.ts +0 -19
- package/test/fixture/skills/agents-sdk/SKILL.md +0 -152
- package/test/fixture/skills/cloudflare/SKILL.md +0 -211
- package/test/fixture/skills/index.json +0 -6
- package/test/fixture/tui-plugin.ts +0 -323
- package/test/fixture/tui-runtime.ts +0 -31
- package/test/format/format.test.ts +0 -272
- package/test/git/git.test.ts +0 -128
- package/test/ide/ide.test.ts +0 -82
- package/test/installation/installation.test.ts +0 -168
- package/test/keybind.test.ts +0 -421
- package/test/lib/effect.ts +0 -53
- package/test/lib/filesystem.ts +0 -10
- package/test/lib/llm-server.ts +0 -778
- package/test/lib/websocket.ts +0 -46
- package/test/lsp/client.test.ts +0 -482
- package/test/lsp/index.test.ts +0 -160
- package/test/lsp/launch.test.ts +0 -22
- package/test/lsp/lifecycle.test.ts +0 -184
- package/test/ltm/ltm.test.ts +0 -230
- package/test/mcp/headers.test.ts +0 -178
- package/test/mcp/lifecycle.test.ts +0 -787
- package/test/mcp/oauth-auto-connect.test.ts +0 -311
- package/test/mcp/oauth-browser.test.ts +0 -276
- package/test/mcp/oauth-callback.test.ts +0 -34
- package/test/memory/abort-leak-webfetch.ts +0 -49
- package/test/memory/abort-leak.test.ts +0 -128
- package/test/patch/patch.test.ts +0 -348
- package/test/permission/arity.test.ts +0 -33
- package/test/permission/next.test.ts +0 -1227
- package/test/permission/next.toConfig.test.ts +0 -110
- package/test/permission-task.test.ts +0 -326
- package/test/plugin/auth-override.test.ts +0 -79
- package/test/plugin/cloudflare.test.ts +0 -68
- package/test/plugin/codex.test.ts +0 -123
- package/test/plugin/github-copilot-models.test.ts +0 -261
- package/test/plugin/install-concurrency.test.ts +0 -140
- package/test/plugin/install.test.ts +0 -570
- package/test/plugin/loader-shared.test.ts +0 -1169
- package/test/plugin/meta.test.ts +0 -137
- package/test/plugin/shared.test.ts +0 -88
- package/test/plugin/trigger.test.ts +0 -102
- package/test/plugin/workspace-adapter.test.ts +0 -109
- package/test/preload.ts +0 -77
- package/test/project/instance.test.ts +0 -276
- package/test/project/migrate-global.test.ts +0 -152
- package/test/project/project.test.ts +0 -600
- package/test/project/vcs.test.ts +0 -286
- package/test/project/worktree-remove.test.ts +0 -126
- package/test/project/worktree.test.ts +0 -223
- package/test/provider/amazon-bedrock.test.ts +0 -462
- package/test/provider/copilot/convert-to-copilot-messages.test.ts +0 -523
- package/test/provider/copilot/copilot-chat-model.test.ts +0 -592
- package/test/provider/gitlab-duo.test.ts +0 -413
- package/test/provider/local.test.ts +0 -208
- package/test/provider/models.test.ts +0 -261
- package/test/provider/provider-category.test.ts +0 -190
- package/test/provider/provider.test.ts +0 -2758
- package/test/provider/transform.test.ts +0 -3681
- package/test/pty/pty-output-isolation.test.ts +0 -147
- package/test/pty/pty-session.test.ts +0 -102
- package/test/pty/pty-shell.test.ts +0 -104
- package/test/question/question.test.ts +0 -490
- package/test/saeeol/agent-global-config-dirs.test.ts +0 -24
- package/test/saeeol/agent-manager-tool.test.ts +0 -71
- package/test/saeeol/agent-permission-overrides.test.ts +0 -75
- package/test/saeeol/agent-skill-permissions.test.ts +0 -37
- package/test/saeeol/ask-agent-permissions.test.ts +0 -303
- package/test/saeeol/bash-hierarchy.test.ts +0 -64
- package/test/saeeol/bash-permission-metadata.test.ts +0 -66
- package/test/saeeol/bash-security-extended.test.ts +0 -243
- package/test/saeeol/bedrock-claude-empty-content.test.ts +0 -138
- package/test/saeeol/boxes-integration.test.ts +0 -415
- package/test/saeeol/builtin-skills.test.ts +0 -75
- package/test/saeeol/cleanup.ts +0 -28
- package/test/saeeol/cli/dev-setup.test.ts +0 -74
- package/test/saeeol/cli/roll-call.test.ts +0 -161
- package/test/saeeol/cli-run-auto-helper.test.ts +0 -58
- package/test/saeeol/codex-auth-refresh.test.ts +0 -124
- package/test/saeeol/commit-message/generate.test.ts +0 -188
- package/test/saeeol/commit-message/git-context.test.ts +0 -303
- package/test/saeeol/commit-message-windows.test.ts +0 -38
- package/test/saeeol/compaction-payload-recovery.test.ts +0 -406
- package/test/saeeol/compaction-preservation-audit.test.ts +0 -122
- package/test/saeeol/compaction-skip-guard.test.ts +0 -224
- package/test/saeeol/compaction-smart-select.test.ts +0 -100
- package/test/saeeol/config/config.test.ts +0 -166
- package/test/saeeol/config/indexing-default-plugin.test.ts +0 -82
- package/test/saeeol/config/opentelemetry-default.test.ts +0 -29
- package/test/saeeol/config-gitignore.test.ts +0 -70
- package/test/saeeol/config-injector.test.ts +0 -305
- package/test/saeeol/config-resilience.test.ts +0 -234
- package/test/saeeol/config-validation.test.ts +0 -183
- package/test/saeeol/cost-propagation.test.ts +0 -94
- package/test/saeeol/cost-tracker-extended.test.ts +0 -141
- package/test/saeeol/cost-tracker.test.ts +0 -64
- package/test/saeeol/custom-provider-delete.test.ts +0 -149
- package/test/saeeol/diff-full.test.ts +0 -226
- package/test/saeeol/edit-permission-filediff.test.ts +0 -223
- package/test/saeeol/encoding.test.ts +0 -364
- package/test/saeeol/enhance-prompt.test.ts +0 -61
- package/test/saeeol/ensure-plan-dir.test.ts +0 -32
- package/test/saeeol/errors.test.ts +0 -144
- package/test/saeeol/external-directory-boundary.test.ts +0 -96
- package/test/saeeol/gateway-headers.test.ts +0 -88
- package/test/saeeol/help.test.ts +0 -191
- package/test/saeeol/ignore-migrator.test.ts +0 -308
- package/test/saeeol/indexing-auth.test.ts +0 -45
- package/test/saeeol/indexing-feature.test.ts +0 -44
- package/test/saeeol/indexing-label.test.ts +0 -70
- package/test/saeeol/indexing-startup.test.ts +0 -381
- package/test/saeeol/indexing-worktree.test.ts +0 -73
- package/test/saeeol/instruction.test.ts +0 -136
- package/test/saeeol/lancedb-runtime.test.ts +0 -116
- package/test/saeeol/loader-auth.test.ts +0 -168
- package/test/saeeol/local-model.test.ts +0 -621
- package/test/saeeol/logo.test.ts +0 -31
- package/test/saeeol/lsp-typescript-lightweight.test.ts +0 -89
- package/test/saeeol/mcp-branding.test.ts +0 -33
- package/test/saeeol/mcp-docker-rm.test.ts +0 -32
- package/test/saeeol/mcp-migrator.test.ts +0 -736
- package/test/saeeol/mcp-oauth-callback.test.ts +0 -33
- package/test/saeeol/memory-io.test.ts +0 -198
- package/test/saeeol/memory-paths.test.ts +0 -87
- package/test/saeeol/memory-security.test.ts +0 -166
- package/test/saeeol/model-cache-org.test.ts +0 -164
- package/test/saeeol/model-info-panel-utils.test.ts +0 -52
- package/test/saeeol/model-info-panel.types.test.ts +0 -7
- package/test/saeeol/models-401-fallback.test.ts +0 -52
- package/test/saeeol/modes-migrator.test.ts +0 -320
- package/test/saeeol/nvidia-headers.test.ts +0 -74
- package/test/saeeol/patch-jsonc.test.ts +0 -73
- package/test/saeeol/patch.test.ts +0 -172
- package/test/saeeol/paths.test.ts +0 -265
- package/test/saeeol/permission/config-paths.test.ts +0 -174
- package/test/saeeol/permission/env-read.test.ts +0 -149
- package/test/saeeol/permission/external-directory-allow.test.ts +0 -327
- package/test/saeeol/permission/next.always-rules.test.ts +0 -882
- package/test/saeeol/permission/next.reply-http.test.ts +0 -205
- package/test/saeeol/permission/next.reply-routing.test.ts +0 -184
- package/test/saeeol/plan-exit-detection.test.ts +0 -494
- package/test/saeeol/plan-followup.test.ts +0 -1376
- package/test/saeeol/project-config-update.test.ts +0 -120
- package/test/saeeol/project-id.test.ts +0 -455
- package/test/saeeol/provider-cost.test.ts +0 -171
- package/test/saeeol/provider-list-failed-state.test.ts +0 -100
- package/test/saeeol/question-dismiss-all.test.ts +0 -174
- package/test/saeeol/read-directory.test.ts +0 -116
- package/test/saeeol/rules-migrator.test.ts +0 -257
- package/test/saeeol/run-auto.test.ts +0 -176
- package/test/saeeol/run-network.test.ts +0 -224
- package/test/saeeol/semantic-search.test.ts +0 -186
- package/test/saeeol/server/permission-allow-everything.test.ts +0 -125
- package/test/saeeol/session/instruction-substitution.test.ts +0 -72
- package/test/saeeol/session/platform-attribution.test.ts +0 -118
- package/test/saeeol/session/session.test.ts +0 -105
- package/test/saeeol/session-compaction-cap.test.ts +0 -399
- package/test/saeeol/session-compaction-chunks.test.ts +0 -501
- package/test/saeeol/session-compaction-safety.test.ts +0 -481
- package/test/saeeol/session-fork-remap.test.ts +0 -251
- package/test/saeeol/session-import-service.test.ts +0 -114
- package/test/saeeol/session-list.test.ts +0 -47
- package/test/saeeol/session-message-metadata.test.ts +0 -128
- package/test/saeeol/session-overflow.test.ts +0 -78
- package/test/saeeol/session-processor-empty-tool-calls.test.ts +0 -571
- package/test/saeeol/session-processor-network-offline.test.ts +0 -204
- package/test/saeeol/session-processor-retry-limit.test.ts +0 -238
- package/test/saeeol/session-processor-review-telemetry.test.ts +0 -82
- package/test/saeeol/session-prompt-compaction-safety.test.ts +0 -517
- package/test/saeeol/session-prompt-queue.test.ts +0 -815
- package/test/saeeol/sessions/inflight-cache.test.ts +0 -157
- package/test/saeeol/sessions/ingest-queue.test.ts +0 -402
- package/test/saeeol/sessions/remote-protocol.test.ts +0 -258
- package/test/saeeol/sessions/remote-sender.test.ts +0 -1036
- package/test/saeeol/sessions/remote-ws.test.ts +0 -367
- package/test/saeeol/sessions/sessions-enable-remote.test.disable +0 -181
- package/test/saeeol/slot-prop-reactivity.test.ts +0 -142
- package/test/saeeol/snapshot-cache.test.ts +0 -84
- package/test/saeeol/snapshot-freeze-repro.test.ts +0 -100
- package/test/saeeol/snapshot-track-timeout.test.ts +0 -519
- package/test/saeeol/stats-subagent-cost.test.ts +0 -123
- package/test/saeeol/suggestion/auto-dismiss.test.ts +0 -65
- package/test/saeeol/suggestion/suggestion.test.ts +0 -145
- package/test/saeeol/suggestion/tool.test.ts +0 -298
- package/test/saeeol/summary-file-diff.test.ts +0 -28
- package/test/saeeol/system-prompt.test.ts +0 -142
- package/test/saeeol/task-nesting.test.ts +0 -193
- package/test/saeeol/telemetry/feedback.test.ts +0 -8
- package/test/saeeol/todo-view.test.ts +0 -57
- package/test/saeeol/tool-encoding.test.ts +0 -455
- package/test/saeeol/tool-registry-indexing-import-failure.test.ts +0 -49
- package/test/saeeol/tool-registry-indexing.test.ts +0 -236
- package/test/saeeol/tool-registry-semantic-import-failure.test.ts +0 -55
- package/test/saeeol/tool-task-model.test.ts +0 -352
- package/test/saeeol/transform-opus-4.7.test.ts +0 -89
- package/test/saeeol/tui-diff.test.ts +0 -91
- package/test/saeeol/tui-sync.test.ts +0 -80
- package/test/saeeol/util/url.test.ts +0 -141
- package/test/saeeol/workflows-migrator.test.ts +0 -261
- package/test/saeeol/worktree-diff-summary.test.ts +0 -64
- package/test/saeeol/worktree-diff.test.ts +0 -223
- package/test/saeeol/worktree-remove-lock.test.ts +0 -82
- package/test/server/AGENTS.md +0 -15
- package/test/server/contract.test.ts +0 -231
- package/test/server/experimental-session-list.test.ts +0 -157
- package/test/server/global-session-list.test.ts +0 -155
- package/test/server/httpapi-authorization.test.ts +0 -103
- package/test/server/httpapi-bridge.test.ts +0 -440
- package/test/server/httpapi-config.test.ts +0 -67
- package/test/server/httpapi-cors.test.ts +0 -89
- package/test/server/httpapi-event.test.ts +0 -57
- package/test/server/httpapi-experimental.test.ts +0 -219
- package/test/server/httpapi-file.test.ts +0 -79
- package/test/server/httpapi-instance-context.test.ts +0 -237
- package/test/server/httpapi-instance.legacy.test.ts +0 -140
- package/test/server/httpapi-instance.test.ts +0 -83
- package/test/server/httpapi-json-parity.test.ts +0 -263
- package/test/server/httpapi-mcp-oauth.test.ts +0 -76
- package/test/server/httpapi-mcp.test.ts +0 -189
- package/test/server/httpapi-provider.test.ts +0 -153
- package/test/server/httpapi-pty-websocket.test.ts +0 -16
- package/test/server/httpapi-pty.test.ts +0 -175
- package/test/server/httpapi-raw-route-auth.test.ts +0 -89
- package/test/server/httpapi-sdk.test.ts +0 -679
- package/test/server/httpapi-session.test.ts +0 -464
- package/test/server/httpapi-sync.test.ts +0 -130
- package/test/server/httpapi-tui.test.ts +0 -121
- package/test/server/httpapi-workspace-routing.test.ts +0 -471
- package/test/server/httpapi-workspace.test.ts +0 -427
- package/test/server/project-init-git.test.ts +0 -113
- package/test/server/proxy-util.test.ts +0 -113
- package/test/server/session-actions.test.ts +0 -49
- package/test/server/session-list.test.ts +0 -238
- package/test/server/session-messages.test.ts +0 -167
- package/test/server/session-select.test.ts +0 -100
- package/test/server/trace-attributes.test.ts +0 -76
- package/test/server/workspace-proxy.test.ts +0 -165
- package/test/server/workspace-routing.test.ts +0 -85
- package/test/session/compaction.test.ts +0 -2420
- package/test/session/instruction.test.ts +0 -247
- package/test/session/llm.test.ts +0 -1273
- package/test/session/message-v2.test.ts +0 -1291
- package/test/session/messages-pagination.test.ts +0 -1173
- package/test/session/network.test.ts +0 -249
- package/test/session/processor-effect.test.ts +0 -847
- package/test/session/prompt.test.ts +0 -2131
- package/test/session/retry.test.ts +0 -340
- package/test/session/revert-compact.test.ts +0 -639
- package/test/session/schema-decoding.test.ts +0 -311
- package/test/session/session-entry-stepper.test.ts +0 -917
- package/test/session/session-schema.test.ts +0 -76
- package/test/session/snapshot-tool-race.test.ts +0 -257
- package/test/session/structured-output-integration.test.ts +0 -265
- package/test/session/structured-output.test.ts +0 -381
- package/test/session/system.test.ts +0 -73
- package/test/share/share-next.test.ts +0 -333
- package/test/shell/shell.test.ts +0 -99
- package/test/skill/discovery.test.ts +0 -116
- package/test/skill/skill.test.ts +0 -393
- package/test/snapshot/snapshot.test.ts +0 -1531
- package/test/storage/db.test.ts +0 -23
- package/test/storage/json-migration.test.ts +0 -832
- package/test/storage/storage.test.ts +0 -293
- package/test/suggestion/suggestion.test.ts +0 -1
- package/test/sync/index.test.ts +0 -256
- package/test/tool/__snapshots__/parameters.test.ts.snap +0 -500
- package/test/tool/__snapshots__/tool.test.ts.snap +0 -9
- package/test/tool/apply_patch.test.ts +0 -614
- package/test/tool/bash.test.ts +0 -1225
- package/test/tool/diagnostics-filter.test.ts +0 -55
- package/test/tool/edit.test.ts +0 -754
- package/test/tool/external-directory.test.ts +0 -169
- package/test/tool/fixtures/large-image.png +0 -0
- package/test/tool/fixtures/models-api.json +0 -65179
- package/test/tool/glob.test.ts +0 -107
- package/test/tool/grep.test.ts +0 -114
- package/test/tool/lsp.test.ts +0 -187
- package/test/tool/parameters.test.ts +0 -243
- package/test/tool/question.test.ts +0 -129
- package/test/tool/read.test.ts +0 -500
- package/test/tool/recall.test.ts +0 -151
- package/test/tool/registry.test.ts +0 -203
- package/test/tool/skill.test.ts +0 -135
- package/test/tool/suggest.test.ts +0 -1
- package/test/tool/task.test.ts +0 -612
- package/test/tool/tool-define.test.ts +0 -99
- package/test/tool/truncation.test.ts +0 -260
- package/test/tool/webfetch.test.ts +0 -103
- package/test/tool/write.test.ts +0 -291
- package/test/util/data-url.test.ts +0 -14
- package/test/util/effect-zod.test.ts +0 -754
- package/test/util/error.test.ts +0 -38
- package/test/util/filesystem.test.ts +0 -656
- package/test/util/format.test.ts +0 -59
- package/test/util/glob.test.ts +0 -164
- package/test/util/iife.test.ts +0 -36
- package/test/util/lazy.test.ts +0 -50
- package/test/util/lock.test.ts +0 -72
- package/test/util/log.test.ts +0 -86
- package/test/util/module.test.ts +0 -59
- package/test/util/process.test.ts +0 -128
- package/test/util/timeout.test.ts +0 -21
- package/test/util/which.test.ts +0 -100
- package/test/util/wildcard.test.ts +0 -90
- package/test/workspace/workspace-restore.test.ts +0 -296
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
// Tests the saeeol-specific patch module guarantees:
|
|
2
|
-
// - Files retain their original encoding after an update (UTF-8 BOM, UTF-16,
|
|
3
|
-
// legacy single-byte, CJK).
|
|
4
|
-
// - Plain UTF-8 files do not gain a spurious BOM.
|
|
5
|
-
// - Moved files keep the original encoding at the new path.
|
|
6
|
-
// These round-trip through Patch.applyPatch directly so we exercise the
|
|
7
|
-
// encoding + BOM integration in patch/index.ts without the tool stack.
|
|
8
|
-
|
|
9
|
-
import { afterEach, beforeEach, describe, expect, test } from "bun:test"
|
|
10
|
-
import fs from "fs/promises"
|
|
11
|
-
import path from "path"
|
|
12
|
-
import { tmpdir } from "os"
|
|
13
|
-
import iconv from "iconv-lite"
|
|
14
|
-
import { Patch } from "../../src/patch"
|
|
15
|
-
|
|
16
|
-
const UTF8_BOM = Buffer.from([0xef, 0xbb, 0xbf])
|
|
17
|
-
const UTF16_LE_BOM = Buffer.from([0xff, 0xfe])
|
|
18
|
-
|
|
19
|
-
describe("Patch encoding preservation", () => {
|
|
20
|
-
let dir: string
|
|
21
|
-
|
|
22
|
-
beforeEach(async () => {
|
|
23
|
-
dir = await fs.mkdtemp(path.join(tmpdir(), "saeeol-patch-"))
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
afterEach(async () => {
|
|
27
|
-
await fs.rm(dir, { recursive: true, force: true })
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
test("preserves UTF-8 BOM through update", async () => {
|
|
31
|
-
const file = path.join(dir, "doc.txt")
|
|
32
|
-
await fs.writeFile(file, Buffer.concat([UTF8_BOM, Buffer.from("line 1\nline 2\n", "utf-8")]))
|
|
33
|
-
|
|
34
|
-
const patch = `*** Begin Patch
|
|
35
|
-
*** Update File: ${file}
|
|
36
|
-
@@
|
|
37
|
-
line 1
|
|
38
|
-
-line 2
|
|
39
|
-
+line 2 updated
|
|
40
|
-
*** End Patch`
|
|
41
|
-
|
|
42
|
-
await Patch.applyPatch(patch)
|
|
43
|
-
|
|
44
|
-
const bytes = await fs.readFile(file)
|
|
45
|
-
expect(bytes.subarray(0, 3).equals(UTF8_BOM)).toBe(true)
|
|
46
|
-
expect(bytes.subarray(3).toString("utf-8")).toBe("line 1\nline 2 updated\n")
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
test("does not introduce BOM for plain UTF-8 files", async () => {
|
|
50
|
-
const file = path.join(dir, "plain.txt")
|
|
51
|
-
await fs.writeFile(file, "line 1\nline 2\n", "utf-8")
|
|
52
|
-
|
|
53
|
-
const patch = `*** Begin Patch
|
|
54
|
-
*** Update File: ${file}
|
|
55
|
-
@@
|
|
56
|
-
line 1
|
|
57
|
-
-line 2
|
|
58
|
-
+line 2 updated
|
|
59
|
-
*** End Patch`
|
|
60
|
-
|
|
61
|
-
await Patch.applyPatch(patch)
|
|
62
|
-
|
|
63
|
-
const bytes = await fs.readFile(file)
|
|
64
|
-
expect(bytes[0]).not.toBe(0xef)
|
|
65
|
-
expect(bytes.toString("utf-8")).toBe("line 1\nline 2 updated\n")
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
test("preserves UTF-16 LE encoding through update", async () => {
|
|
69
|
-
const file = path.join(dir, "utf16.txt")
|
|
70
|
-
await fs.writeFile(file, Buffer.concat([UTF16_LE_BOM, iconv.encode("line 1\nline 2\n", "utf-16le")]))
|
|
71
|
-
|
|
72
|
-
const patch = `*** Begin Patch
|
|
73
|
-
*** Update File: ${file}
|
|
74
|
-
@@
|
|
75
|
-
line 1
|
|
76
|
-
-line 2
|
|
77
|
-
+line 2 updated
|
|
78
|
-
*** End Patch`
|
|
79
|
-
|
|
80
|
-
await Patch.applyPatch(patch)
|
|
81
|
-
|
|
82
|
-
const bytes = await fs.readFile(file)
|
|
83
|
-
expect(bytes.subarray(0, 2).equals(UTF16_LE_BOM)).toBe(true)
|
|
84
|
-
expect(iconv.decode(bytes.subarray(2), "utf-16le")).toBe("line 1\nline 2 updated\n")
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
test("preserves iso-8859-1 encoding through update", async () => {
|
|
88
|
-
const file = path.join(dir, "latin1.txt")
|
|
89
|
-
await fs.writeFile(file, iconv.encode("café\nñandú\n", "iso-8859-1"))
|
|
90
|
-
|
|
91
|
-
const patch = `*** Begin Patch
|
|
92
|
-
*** Update File: ${file}
|
|
93
|
-
@@
|
|
94
|
-
café
|
|
95
|
-
-ñandú
|
|
96
|
-
+águila
|
|
97
|
-
*** End Patch`
|
|
98
|
-
|
|
99
|
-
await Patch.applyPatch(patch)
|
|
100
|
-
|
|
101
|
-
const bytes = await fs.readFile(file)
|
|
102
|
-
expect(iconv.decode(bytes, "iso-8859-1")).toBe("café\náguila\n")
|
|
103
|
-
// á and ñ are two bytes in UTF-8, one byte in ISO-8859-1. If the file had
|
|
104
|
-
// been silently re-encoded as UTF-8 the byte length would differ.
|
|
105
|
-
expect(bytes.length).toBe("café\náguila\n".length)
|
|
106
|
-
})
|
|
107
|
-
|
|
108
|
-
test("preserves Shift_JIS encoding through update", async () => {
|
|
109
|
-
const file = path.join(dir, "jp.txt")
|
|
110
|
-
// chardet needs enough characteristic bytes to identify Shift_JIS. A
|
|
111
|
-
// single 19-byte phrase looks like windows-1252, so the sample is padded
|
|
112
|
-
// to match the body of Japanese text the tool tests already rely on.
|
|
113
|
-
const sample = "こんにちは、世界!日本語のテストです。"
|
|
114
|
-
await fs.writeFile(file, iconv.encode(`line1\n${sample}\nline3\n`, "Shift_JIS"))
|
|
115
|
-
|
|
116
|
-
const patch = `*** Begin Patch
|
|
117
|
-
*** Update File: ${file}
|
|
118
|
-
@@
|
|
119
|
-
line1
|
|
120
|
-
-${sample}
|
|
121
|
-
+さようなら、世界!
|
|
122
|
-
line3
|
|
123
|
-
*** End Patch`
|
|
124
|
-
|
|
125
|
-
await Patch.applyPatch(patch)
|
|
126
|
-
|
|
127
|
-
const bytes = await fs.readFile(file)
|
|
128
|
-
expect(iconv.decode(bytes, "Shift_JIS")).toBe("line1\nさようなら、世界!\nline3\n")
|
|
129
|
-
const utf8Rendered = Buffer.from("line1\nさようなら、世界!\nline3\n", "utf-8")
|
|
130
|
-
expect(bytes.equals(utf8Rendered)).toBe(false)
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
test("preserves UTF-8 BOM when file is moved", async () => {
|
|
134
|
-
const from = path.join(dir, "old.txt")
|
|
135
|
-
const to = path.join(dir, "new.txt")
|
|
136
|
-
await fs.writeFile(from, Buffer.concat([UTF8_BOM, Buffer.from("original\n", "utf-8")]))
|
|
137
|
-
|
|
138
|
-
const patch = `*** Begin Patch
|
|
139
|
-
*** Update File: ${from}
|
|
140
|
-
*** Move to: ${to}
|
|
141
|
-
@@
|
|
142
|
-
-original
|
|
143
|
-
+updated
|
|
144
|
-
*** End Patch`
|
|
145
|
-
|
|
146
|
-
await Patch.applyPatch(patch)
|
|
147
|
-
|
|
148
|
-
const moved = await fs.readFile(to)
|
|
149
|
-
expect(moved.subarray(0, 3).equals(UTF8_BOM)).toBe(true)
|
|
150
|
-
expect(moved.subarray(3).toString("utf-8")).toBe("updated\n")
|
|
151
|
-
|
|
152
|
-
const oldExists = await fs
|
|
153
|
-
.access(from)
|
|
154
|
-
.then(() => true)
|
|
155
|
-
.catch(() => false)
|
|
156
|
-
expect(oldExists).toBe(false)
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
test("new files added via patch are written as plain UTF-8", async () => {
|
|
160
|
-
const file = path.join(dir, "new.txt")
|
|
161
|
-
const patch = `*** Begin Patch
|
|
162
|
-
*** Add File: ${file}
|
|
163
|
-
+hello world
|
|
164
|
-
*** End Patch`
|
|
165
|
-
|
|
166
|
-
await Patch.applyPatch(patch)
|
|
167
|
-
|
|
168
|
-
const bytes = await fs.readFile(file)
|
|
169
|
-
expect(bytes[0]).not.toBe(0xef)
|
|
170
|
-
expect(bytes.toString("utf-8")).toBe("hello world")
|
|
171
|
-
})
|
|
172
|
-
})
|
|
@@ -1,265 +0,0 @@
|
|
|
1
|
-
import { test, expect, describe } from "bun:test"
|
|
2
|
-
import { SaeeolPaths } from "../../src/overlay/paths"
|
|
3
|
-
import { tmpdir } from "../fixture/fixture"
|
|
4
|
-
import path from "path"
|
|
5
|
-
import fs from "fs/promises"
|
|
6
|
-
|
|
7
|
-
async function withHome<T>(home: string, fn: () => Promise<T>): Promise<T> {
|
|
8
|
-
const prev = process.env.HOME
|
|
9
|
-
process.env.HOME = home
|
|
10
|
-
try {
|
|
11
|
-
return await fn()
|
|
12
|
-
} finally {
|
|
13
|
-
if (prev) process.env.HOME = prev
|
|
14
|
-
else delete process.env.HOME
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
describe("SaeeolPaths", () => {
|
|
19
|
-
describe("skillDirectories", () => {
|
|
20
|
-
test("discovers skills from .saeeol/skills/", async () => {
|
|
21
|
-
await using tmp = await tmpdir({
|
|
22
|
-
init: async (dir) => {
|
|
23
|
-
const skillDir = path.join(dir, ".saeeol", "skills", "test-skill")
|
|
24
|
-
await fs.mkdir(skillDir, { recursive: true })
|
|
25
|
-
await Bun.write(
|
|
26
|
-
path.join(skillDir, "SKILL.md"),
|
|
27
|
-
`---
|
|
28
|
-
name: test-skill
|
|
29
|
-
description: A test skill
|
|
30
|
-
---
|
|
31
|
-
# Test instructions`,
|
|
32
|
-
)
|
|
33
|
-
},
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
const result = await SaeeolPaths.skillDirectories({
|
|
37
|
-
projectDir: tmp.path,
|
|
38
|
-
worktreeRoot: tmp.path,
|
|
39
|
-
skipGlobalPaths: true,
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
expect(result).toHaveLength(1)
|
|
43
|
-
expect(result[0]).toEndWith(".saeeol")
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
test("returns empty array when no .saeeol/skills/ exists", async () => {
|
|
47
|
-
await using tmp = await tmpdir()
|
|
48
|
-
|
|
49
|
-
const result = await SaeeolPaths.skillDirectories({
|
|
50
|
-
projectDir: tmp.path,
|
|
51
|
-
worktreeRoot: tmp.path,
|
|
52
|
-
skipGlobalPaths: true,
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
expect(result).toHaveLength(0)
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
test("discovers skills from nested .saeeol directories", async () => {
|
|
59
|
-
await using tmp = await tmpdir({
|
|
60
|
-
init: async (dir) => {
|
|
61
|
-
// Root level skill
|
|
62
|
-
const rootSkillDir = path.join(dir, ".saeeol", "skills", "root-skill")
|
|
63
|
-
await fs.mkdir(rootSkillDir, { recursive: true })
|
|
64
|
-
await Bun.write(
|
|
65
|
-
path.join(rootSkillDir, "SKILL.md"),
|
|
66
|
-
`---
|
|
67
|
-
name: root-skill
|
|
68
|
-
description: Root level skill
|
|
69
|
-
---
|
|
70
|
-
# Root instructions`,
|
|
71
|
-
)
|
|
72
|
-
|
|
73
|
-
// Nested project skill
|
|
74
|
-
const nestedDir = path.join(dir, "packages", "nested")
|
|
75
|
-
const nestedSkillDir = path.join(nestedDir, ".saeeol", "skills", "nested-skill")
|
|
76
|
-
await fs.mkdir(nestedSkillDir, { recursive: true })
|
|
77
|
-
await Bun.write(
|
|
78
|
-
path.join(nestedSkillDir, "SKILL.md"),
|
|
79
|
-
`---
|
|
80
|
-
name: nested-skill
|
|
81
|
-
description: Nested skill
|
|
82
|
-
---
|
|
83
|
-
# Nested instructions`,
|
|
84
|
-
)
|
|
85
|
-
},
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
// Run from nested directory, should find both
|
|
89
|
-
const nestedPath = path.join(tmp.path, "packages", "nested")
|
|
90
|
-
const result = await SaeeolPaths.skillDirectories({
|
|
91
|
-
projectDir: nestedPath,
|
|
92
|
-
worktreeRoot: tmp.path,
|
|
93
|
-
skipGlobalPaths: true,
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
expect(result).toHaveLength(2)
|
|
97
|
-
const nested = path.join("packages", "nested")
|
|
98
|
-
expect(result.some((d) => d.includes(nested))).toBe(true)
|
|
99
|
-
expect(result.some((d) => !d.includes(nested))).toBe(true)
|
|
100
|
-
})
|
|
101
|
-
|
|
102
|
-
test("handles .saeeol directory without skills subdirectory", async () => {
|
|
103
|
-
await using tmp = await tmpdir({
|
|
104
|
-
init: async (dir) => {
|
|
105
|
-
// Create .saeeol but not skills/
|
|
106
|
-
await fs.mkdir(path.join(dir, ".saeeol"), { recursive: true })
|
|
107
|
-
await Bun.write(path.join(dir, ".saeeol", "config.json"), "{}")
|
|
108
|
-
},
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
const result = await SaeeolPaths.skillDirectories({
|
|
112
|
-
projectDir: tmp.path,
|
|
113
|
-
worktreeRoot: tmp.path,
|
|
114
|
-
skipGlobalPaths: true,
|
|
115
|
-
})
|
|
116
|
-
|
|
117
|
-
expect(result).toHaveLength(0)
|
|
118
|
-
})
|
|
119
|
-
|
|
120
|
-
test("handles symlinked skill directories", async () => {
|
|
121
|
-
await using tmp = await tmpdir({
|
|
122
|
-
init: async (dir) => {
|
|
123
|
-
// Create actual skill in a different location
|
|
124
|
-
const actualDir = path.join(dir, "shared-skills", "my-skill")
|
|
125
|
-
await fs.mkdir(actualDir, { recursive: true })
|
|
126
|
-
await Bun.write(
|
|
127
|
-
path.join(actualDir, "SKILL.md"),
|
|
128
|
-
`---
|
|
129
|
-
name: my-skill
|
|
130
|
-
description: Symlinked skill
|
|
131
|
-
---
|
|
132
|
-
# Instructions`,
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
// Create .saeeol/skills/ and symlink the skill
|
|
136
|
-
const skillsDir = path.join(dir, ".saeeol", "skills")
|
|
137
|
-
await fs.mkdir(skillsDir, { recursive: true })
|
|
138
|
-
await fs.symlink(actualDir, path.join(skillsDir, "my-skill"))
|
|
139
|
-
},
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
const result = await SaeeolPaths.skillDirectories({
|
|
143
|
-
projectDir: tmp.path,
|
|
144
|
-
worktreeRoot: tmp.path,
|
|
145
|
-
skipGlobalPaths: true,
|
|
146
|
-
})
|
|
147
|
-
|
|
148
|
-
expect(result).toHaveLength(1)
|
|
149
|
-
expect(result[0]).toEndWith(".saeeol")
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
test("discovers skills from .saeeol/skills/", async () => {
|
|
153
|
-
await using tmp = await tmpdir({
|
|
154
|
-
init: async (dir) => {
|
|
155
|
-
const skillDir = path.join(dir, ".saeeol", "skills", "legacy-skill")
|
|
156
|
-
await fs.mkdir(skillDir, { recursive: true })
|
|
157
|
-
await Bun.write(
|
|
158
|
-
path.join(skillDir, "SKILL.md"),
|
|
159
|
-
`---
|
|
160
|
-
name: legacy-skill
|
|
161
|
-
description: A legacy skill
|
|
162
|
-
---
|
|
163
|
-
# Legacy instructions`,
|
|
164
|
-
)
|
|
165
|
-
},
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
const result = await SaeeolPaths.skillDirectories({
|
|
169
|
-
projectDir: tmp.path,
|
|
170
|
-
worktreeRoot: tmp.path,
|
|
171
|
-
skipGlobalPaths: true,
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
expect(result).toHaveLength(1)
|
|
175
|
-
expect(result[0]).toEndWith(".saeeol")
|
|
176
|
-
})
|
|
177
|
-
|
|
178
|
-
test("returns skill dirs from .saeeol", async () => {
|
|
179
|
-
await using tmp = await tmpdir({
|
|
180
|
-
init: async (dir) => {
|
|
181
|
-
// .saeeol skill
|
|
182
|
-
const saeeolSkillDir = path.join(dir, ".saeeol", "skills", "new-skill")
|
|
183
|
-
await fs.mkdir(saeeolSkillDir, { recursive: true })
|
|
184
|
-
await Bun.write(path.join(saeeolSkillDir, "SKILL.md"), "# New skill")
|
|
185
|
-
|
|
186
|
-
// .saeeol skill
|
|
187
|
-
const legacySkillDir = path.join(dir, ".saeeol", "skills", "old-skill")
|
|
188
|
-
await fs.mkdir(legacySkillDir, { recursive: true })
|
|
189
|
-
await Bun.write(path.join(legacySkillDir, "SKILL.md"), "# Old skill")
|
|
190
|
-
},
|
|
191
|
-
})
|
|
192
|
-
|
|
193
|
-
const result = await SaeeolPaths.skillDirectories({
|
|
194
|
-
projectDir: tmp.path,
|
|
195
|
-
worktreeRoot: tmp.path,
|
|
196
|
-
skipGlobalPaths: true,
|
|
197
|
-
})
|
|
198
|
-
|
|
199
|
-
expect(result).toHaveLength(1)
|
|
200
|
-
expect(result[0]).toEndWith(".saeeol")
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
test("discovers global skills from ~/.saeeol/skills/", async () => {
|
|
204
|
-
await using tmp = await tmpdir({
|
|
205
|
-
init: async (dir) => {
|
|
206
|
-
const skillDir = path.join(dir, ".saeeol", "skills", "global-skill")
|
|
207
|
-
await fs.mkdir(skillDir, { recursive: true })
|
|
208
|
-
await Bun.write(path.join(skillDir, "SKILL.md"), "# Global skill")
|
|
209
|
-
await fs.mkdir(path.join(dir, "repo"), { recursive: true })
|
|
210
|
-
},
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
const result = await withHome(tmp.path, () =>
|
|
214
|
-
SaeeolPaths.skillDirectories({
|
|
215
|
-
projectDir: path.join(tmp.path, "repo"),
|
|
216
|
-
worktreeRoot: path.join(tmp.path, "repo"),
|
|
217
|
-
}),
|
|
218
|
-
)
|
|
219
|
-
|
|
220
|
-
expect(result.some((d) => d.endsWith(".saeeol"))).toBe(true)
|
|
221
|
-
})
|
|
222
|
-
|
|
223
|
-
test("discovers multiple skills in same directory", async () => {
|
|
224
|
-
await using tmp = await tmpdir({
|
|
225
|
-
init: async (dir) => {
|
|
226
|
-
const skillsDir = path.join(dir, ".saeeol", "skills")
|
|
227
|
-
|
|
228
|
-
// First skill
|
|
229
|
-
const skill1 = path.join(skillsDir, "skill-one")
|
|
230
|
-
await fs.mkdir(skill1, { recursive: true })
|
|
231
|
-
await Bun.write(
|
|
232
|
-
path.join(skill1, "SKILL.md"),
|
|
233
|
-
`---
|
|
234
|
-
name: skill-one
|
|
235
|
-
description: First skill
|
|
236
|
-
---
|
|
237
|
-
# First`,
|
|
238
|
-
)
|
|
239
|
-
|
|
240
|
-
// Second skill
|
|
241
|
-
const skill2 = path.join(skillsDir, "skill-two")
|
|
242
|
-
await fs.mkdir(skill2, { recursive: true })
|
|
243
|
-
await Bun.write(
|
|
244
|
-
path.join(skill2, "SKILL.md"),
|
|
245
|
-
`---
|
|
246
|
-
name: skill-two
|
|
247
|
-
description: Second skill
|
|
248
|
-
---
|
|
249
|
-
# Second`,
|
|
250
|
-
)
|
|
251
|
-
},
|
|
252
|
-
})
|
|
253
|
-
|
|
254
|
-
const result = await SaeeolPaths.skillDirectories({
|
|
255
|
-
projectDir: tmp.path,
|
|
256
|
-
worktreeRoot: tmp.path,
|
|
257
|
-
skipGlobalPaths: true,
|
|
258
|
-
})
|
|
259
|
-
|
|
260
|
-
// Should return the .saeeol directory (not skills/ subdirectory)
|
|
261
|
-
expect(result).toHaveLength(1)
|
|
262
|
-
expect(result[0]).toEndWith(".saeeol")
|
|
263
|
-
})
|
|
264
|
-
})
|
|
265
|
-
})
|
|
@@ -1,174 +0,0 @@
|
|
|
1
|
-
import path from "path"
|
|
2
|
-
import { describe, expect, test } from "bun:test"
|
|
3
|
-
import { ConfigProtection } from "../../../src/overlay/permission/config-paths"
|
|
4
|
-
import { Global } from "@saeeol/core/global"
|
|
5
|
-
import { SaeeolPaths } from "../../../src/overlay/paths"
|
|
6
|
-
|
|
7
|
-
describe("ConfigProtection.isRequest", () => {
|
|
8
|
-
const config = path.resolve(Global.Path.config)
|
|
9
|
-
const legacy = SaeeolPaths.globalDirs().map((d) => path.resolve(d))
|
|
10
|
-
|
|
11
|
-
// --- external_directory: bash-originated (empty metadata) ---
|
|
12
|
-
|
|
13
|
-
test("returns true for bash external_directory targeting global config", () => {
|
|
14
|
-
const result = ConfigProtection.isRequest({
|
|
15
|
-
permission: "external_directory",
|
|
16
|
-
patterns: [config + "/*"],
|
|
17
|
-
metadata: {},
|
|
18
|
-
})
|
|
19
|
-
expect(result).toBe(true)
|
|
20
|
-
})
|
|
21
|
-
|
|
22
|
-
test("returns true for bash external_directory targeting skill dir", () => {
|
|
23
|
-
const result = ConfigProtection.isRequest({
|
|
24
|
-
permission: "external_directory",
|
|
25
|
-
patterns: [path.join(config, "skills", "my-skill") + "/*"],
|
|
26
|
-
metadata: {},
|
|
27
|
-
})
|
|
28
|
-
expect(result).toBe(true)
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
test("returns true for bash external_directory targeting legacy global dir", () => {
|
|
32
|
-
for (const dir of legacy) {
|
|
33
|
-
const result = ConfigProtection.isRequest({
|
|
34
|
-
permission: "external_directory",
|
|
35
|
-
patterns: [dir + "/*"],
|
|
36
|
-
metadata: {},
|
|
37
|
-
})
|
|
38
|
-
expect(result).toBe(true)
|
|
39
|
-
}
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
// --- external_directory: file-tool-originated (has metadata.filepath) ---
|
|
43
|
-
|
|
44
|
-
test("returns false for file-tool external_directory targeting global config", () => {
|
|
45
|
-
const result = ConfigProtection.isRequest({
|
|
46
|
-
permission: "external_directory",
|
|
47
|
-
patterns: [config + "/*"],
|
|
48
|
-
metadata: { filepath: path.join(config, "saeeol.json"), parentDir: config },
|
|
49
|
-
})
|
|
50
|
-
expect(result).toBe(false)
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
test("returns false for file-tool external_directory targeting global config root dir", () => {
|
|
54
|
-
const result = ConfigProtection.isRequest({
|
|
55
|
-
permission: "external_directory",
|
|
56
|
-
patterns: [config + "/*"],
|
|
57
|
-
metadata: { filepath: config, parentDir: config },
|
|
58
|
-
})
|
|
59
|
-
expect(result).toBe(false)
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
test("returns false for file-tool external_directory targeting readable global command dir", () => {
|
|
63
|
-
const result = ConfigProtection.isRequest({
|
|
64
|
-
permission: "external_directory",
|
|
65
|
-
patterns: [path.join(config, "command") + "/*"],
|
|
66
|
-
metadata: { filepath: path.join(config, "command", "foo.md"), parentDir: path.join(config, "command") },
|
|
67
|
-
})
|
|
68
|
-
expect(result).toBe(false)
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
test("returns false for file-tool external_directory targeting readable global skill dir", () => {
|
|
72
|
-
const result = ConfigProtection.isRequest({
|
|
73
|
-
permission: "external_directory",
|
|
74
|
-
patterns: [path.join(config, "skills") + "/*"],
|
|
75
|
-
metadata: {
|
|
76
|
-
filepath: path.join(config, "skills", "my-skill", "SKILL.md"),
|
|
77
|
-
parentDir: path.join(config, "skills"),
|
|
78
|
-
},
|
|
79
|
-
})
|
|
80
|
-
expect(result).toBe(false)
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
// --- external_directory: non-config dirs ---
|
|
84
|
-
|
|
85
|
-
test("returns false for bash external_directory targeting non-config dir", () => {
|
|
86
|
-
const result = ConfigProtection.isRequest({
|
|
87
|
-
permission: "external_directory",
|
|
88
|
-
patterns: ["/tmp/some-project/*"],
|
|
89
|
-
metadata: {},
|
|
90
|
-
})
|
|
91
|
-
expect(result).toBe(false)
|
|
92
|
-
})
|
|
93
|
-
|
|
94
|
-
// --- edit permission ---
|
|
95
|
-
|
|
96
|
-
test("returns true for edit targeting global config file via metadata.filepath", () => {
|
|
97
|
-
const result = ConfigProtection.isRequest({
|
|
98
|
-
permission: "edit",
|
|
99
|
-
patterns: [],
|
|
100
|
-
metadata: { filepath: path.join(config, "config.json") },
|
|
101
|
-
})
|
|
102
|
-
expect(result).toBe(true)
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
test("returns true for edit targeting skill file via metadata.filepath", () => {
|
|
106
|
-
const result = ConfigProtection.isRequest({
|
|
107
|
-
permission: "edit",
|
|
108
|
-
patterns: [],
|
|
109
|
-
metadata: { filepath: path.join(config, "skills", "my-skill", "SKILL.md") },
|
|
110
|
-
})
|
|
111
|
-
expect(result).toBe(true)
|
|
112
|
-
})
|
|
113
|
-
|
|
114
|
-
test("returns true for edit targeting legacy global dir via metadata.filepath", () => {
|
|
115
|
-
for (const dir of legacy) {
|
|
116
|
-
const result = ConfigProtection.isRequest({
|
|
117
|
-
permission: "edit",
|
|
118
|
-
patterns: [],
|
|
119
|
-
metadata: { filepath: path.join(dir, "config.json") },
|
|
120
|
-
})
|
|
121
|
-
expect(result).toBe(true)
|
|
122
|
-
}
|
|
123
|
-
})
|
|
124
|
-
|
|
125
|
-
test("returns true for edit targeting relative config path via patterns", () => {
|
|
126
|
-
const result = ConfigProtection.isRequest({
|
|
127
|
-
permission: "edit",
|
|
128
|
-
patterns: [".saeeol/command/foo.md"],
|
|
129
|
-
})
|
|
130
|
-
expect(result).toBe(true)
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
test("returns false for edit targeting excluded subdir (plans)", () => {
|
|
134
|
-
const result = ConfigProtection.isRequest({
|
|
135
|
-
permission: "edit",
|
|
136
|
-
patterns: [".saeeol/plans/plan.md"],
|
|
137
|
-
})
|
|
138
|
-
expect(result).toBe(false)
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
test("returns false for read permission", () => {
|
|
142
|
-
const result = ConfigProtection.isRequest({
|
|
143
|
-
permission: "read",
|
|
144
|
-
patterns: [".saeeol/config.json"],
|
|
145
|
-
})
|
|
146
|
-
expect(result).toBe(false)
|
|
147
|
-
})
|
|
148
|
-
|
|
149
|
-
test("returns false for bash permission", () => {
|
|
150
|
-
const result = ConfigProtection.isRequest({
|
|
151
|
-
permission: "bash",
|
|
152
|
-
patterns: ["cat " + path.join(config, "config.json")],
|
|
153
|
-
})
|
|
154
|
-
expect(result).toBe(false)
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
test("returns true for edit targeting root config files", () => {
|
|
158
|
-
for (const file of ["saeeol.json", "saeeol.jsonc", "AGENTS.md"]) {
|
|
159
|
-
const result = ConfigProtection.isRequest({
|
|
160
|
-
permission: "edit",
|
|
161
|
-
patterns: [file],
|
|
162
|
-
})
|
|
163
|
-
expect(result).toBe(true)
|
|
164
|
-
}
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
test("returns false for edit targeting non-config files", () => {
|
|
168
|
-
const result = ConfigProtection.isRequest({
|
|
169
|
-
permission: "edit",
|
|
170
|
-
patterns: ["src/index.ts"],
|
|
171
|
-
})
|
|
172
|
-
expect(result).toBe(false)
|
|
173
|
-
})
|
|
174
|
-
})
|