@xopcai/xopc 0.0.100 → 0.0.102
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/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
- package/dist/extensions/feishu/src/workflow-progress.js +1 -1
- package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
- package/dist/extensions/telegram/src/inbound-processor.js +1 -1
- package/dist/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/telegram/src/update-offset-store.js +1 -1
- package/dist/extensions/telegram/src/workflow-progress.js +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/extensions/weixin/src/api/api.js +7 -5
- package/dist/extensions/weixin/src/api/api.js.map +1 -1
- package/dist/extensions/weixin/src/auth/accounts.js +1 -1
- package/dist/extensions/weixin/src/cdn/upload.js +1 -1
- package/dist/extensions/weixin/src/media/data-url.js +1 -1
- package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
- package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
- package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
- package/dist/extensions/weixin/src/workflow-progress.js +1 -1
- package/dist/gateway/static/root/assets/{agents-C5jtBK-H.js → agents-DQ0mQxIA.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-smJl-qf_.js → apps-page-Uv4kOmDE.js} +1 -1
- package/dist/gateway/static/root/assets/{attachment-preview-renderer-DBAxQXb-.js → attachment-preview-renderer-CybMSIoS.js} +2 -2
- package/dist/gateway/static/root/assets/{attachment-process-heavy-Csq3TrrP.js → attachment-process-heavy-RnGYy9bC.js} +2 -2
- package/dist/gateway/static/root/assets/{channels-settings-CH6KgFK6.js → channels-settings-BEtP53V6.js} +1 -1
- package/dist/gateway/static/root/assets/{channels-status-swr-CV70xvY7.js → channels-status-swr-CxTtS1hI.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-api-CgBO8B7I.js → cron-api-CznlPIZT.js} +1 -1
- package/dist/gateway/static/root/assets/{cron-page-Be0cW1cR.js → cron-page-Dx6dE3eD.js} +1 -1
- package/dist/gateway/static/root/assets/{dist-P8HRGUuh.js → dist-DH4IuRV0.js} +1 -1
- package/dist/gateway/static/root/assets/{docx-preview-Dxj1EkCO.js → docx-preview-CajIk2FR.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-BowuycYu.js → extension-debug-page-BNkhvRQW.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-27-Zpv8O.js → extension-page-CcIGQah2.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-DDFa_rIq.js → extension-settings-page-DuDCSb3J.js} +1 -1
- package/dist/gateway/static/root/assets/{field-primitives-BWLssxEb.js → field-primitives-BUwUiDf5.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-BVuYNYT_.js → heartbeat-config-api-BjFW1cl-.js} +1 -1
- package/dist/gateway/static/root/assets/{index-CRDAmr3W.js → index-DKgHC1Ta.js} +9 -9
- package/dist/gateway/static/root/assets/{logs-page-BDX8IrDQ.js → logs-page-CiG0m81R.js} +1 -1
- package/dist/gateway/static/root/assets/{note-detail-page-BmQ9KeiA.js → note-detail-page-DG3DVFTf.js} +2 -2
- package/dist/gateway/static/root/assets/{note-time-14I9Sgqh.js → note-time-DjlllCF3.js} +1 -1
- package/dist/gateway/static/root/assets/{notes-page-BMfP0FFf.js → notes-page-D40ZpS0Y.js} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-C3scyChq.js → sessions-page-BvtdbmW8.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-advanced-gate-2ODuCjHP.js → settings-advanced-gate-BQamRjkV.js} +2 -2
- package/dist/gateway/static/root/assets/{settings-form-section-DUoGKAiW.js → settings-form-section-C3_sEFfD.js} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-CttAfOWV.js → settings-page-D972_jaS.js} +2 -2
- package/dist/gateway/static/root/assets/{share-preview-page-B77xqiiI.js → share-preview-page-CKCTMo0_.js} +2 -2
- package/dist/gateway/static/root/assets/{skills-page-B_bAZGzB.js → skills-page-QwFCB4yV.js} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-BgCPrmxU.js → theme-store-B6KXPHgK.js} +1 -1
- package/dist/gateway/static/root/assets/{utils-CCGejlcX.js → utils-DCm11_KW.js} +1 -1
- package/dist/gateway/static/root/assets/{voice-api-key-field-DZzzihcY.js → voice-api-key-field-CywiB7Dw.js} +1 -1
- package/dist/gateway/static/root/assets/{workflow-page.utils-D5RMAmT4.js → workflow-page.utils-g57BRfEd.js} +1 -1
- package/dist/gateway/static/root/assets/{workflows-page-DEYpC6Bv.js → workflows-page-Be7l_SWw.js} +1 -1
- package/dist/gateway/static/root/index.html +2 -2
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.js +23 -7
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/agent-scope.js +1 -1
- package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
- package/dist/src/agent/context/workspace-seed.js +2 -2
- package/dist/src/agent/context/workspace-state.js +1 -1
- package/dist/src/agent/embedded/run-for-session.js +1 -0
- package/dist/src/agent/embedded/run-for-session.js.map +1 -1
- package/dist/src/agent/goals/goal-run-store.js +4 -4
- package/dist/src/agent/goals/persistent-goal-service.js +1 -1
- package/dist/src/agent/goals/post-turn.js +2 -2
- package/dist/src/agent/image/load-image-media.js +2 -2
- package/dist/src/agent/ipc/bus.js +1 -1
- package/dist/src/agent/ipc/inbox.js +2 -2
- package/dist/src/agent/ipc/socket.js +1 -1
- package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
- package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
- package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
- package/dist/src/agent/mcp/mcp-transport.js +1 -1
- package/dist/src/agent/memory/builtin-memory-store.js +1 -1
- package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
- package/dist/src/agent/memory/dreaming/events.js +1 -1
- package/dist/src/agent/memory/dreaming/last-run.js +1 -1
- package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
- package/dist/src/agent/memory/dreaming/preview.js +1 -1
- package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
- package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
- package/dist/src/agent/memory/dreaming/utils.js +1 -1
- package/dist/src/agent/memory/memory-flush.js +1 -1
- package/dist/src/agent/memory/plugin-discovery.js +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
- package/dist/src/agent/reply/post-compaction-context.js +1 -1
- package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
- package/dist/src/agent/sandbox/path-policy.js +2 -2
- package/dist/src/agent/service.js +4 -4
- package/dist/src/agent/session/session-inspector.js +1 -1
- package/dist/src/agent/skills/config.js +1 -1
- package/dist/src/agent/skills/hub-hash.js +2 -2
- package/dist/src/agent/skills/hub-lock.js +1 -1
- package/dist/src/agent/skills/hub-pull.js +2 -2
- package/dist/src/agent/skills/index.js +1 -1
- package/dist/src/agent/skills/managed-store.js +1 -1
- package/dist/src/agent/skills/scanner.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +1 -1
- package/dist/src/agent/skills/skill-manager.js +1 -1
- package/dist/src/agent/tools/dreaming-tool.js +1 -1
- package/dist/src/agent/tools/factory.js +1 -1
- package/dist/src/agent/tools/image-generate-tool.js +1 -1
- package/dist/src/agent/tools/send-media.js +1 -1
- package/dist/src/agent/tools/skill-manage-tool.js +1 -1
- package/dist/src/agent/tools/workflow-tool.js +1 -1
- package/dist/src/agent/tools/write.js +1 -1
- package/dist/src/agent/workflow/catalog.js +1 -1
- package/dist/src/auth/credentials.js +3 -4
- package/dist/src/auth/credentials.js.map +1 -1
- package/dist/src/auth/profiles/store.js +1 -1
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/browser/cache-dir-policy.js +1 -1
- package/dist/src/browser/cdp-local-launcher.js +2 -2
- package/dist/src/browser/providers/browser-ext-install.js +3 -3
- package/dist/src/browser/providers/cloakbrowser.js +4 -4
- package/dist/src/browser/providers/playwright-doctor.js +1 -1
- package/dist/src/browser/stealth.js +1 -1
- package/dist/src/channels/outbound/persist-store.js +1 -1
- package/dist/src/channels/pairing/allow-from-file.js +1 -1
- package/dist/src/channels/pairing/pairing-store.js +2 -2
- package/dist/src/chat-commands/agent-edit.js +2 -2
- package/dist/src/chat-commands/builtins/config.js +2 -2
- package/dist/src/chat-commands/context.js +1 -1
- package/dist/src/cli/bin.d.ts +1 -0
- package/dist/src/cli/bin.js +1 -0
- package/dist/src/cli/bin.js.map +1 -1
- package/dist/src/cli/commands/config.js +1 -1
- package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
- package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
- package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
- package/dist/src/cli/commands/extension-dev.js +1 -1
- package/dist/src/cli/commands/extension-marketplace.js +1 -1
- package/dist/src/cli/commands/extension-pack.js +1 -1
- package/dist/src/cli/commands/gateway/logs.js +1 -1
- package/dist/src/cli/commands/image.js +1 -1
- package/dist/src/cli/commands/init.js +3 -3
- package/dist/src/cli/utils/init-workspace-core.js +2 -2
- package/dist/src/commands/agents.config.js +1 -1
- package/dist/src/config/agent-profile.js +1 -1
- package/dist/src/config/gateway-bind.js +1 -1
- package/dist/src/config/index.js +5 -5
- package/dist/src/config/loader.js +2 -2
- package/dist/src/config/models-json.js +2 -2
- package/dist/src/config/paths-state.js +1 -1
- package/dist/src/config/profile.js +2 -2
- package/dist/src/config/workspace-path.js +1 -1
- package/dist/src/cron/executor.js +2 -2
- package/dist/src/cron/persistence.js +1 -1
- package/dist/src/daemon/constants.js +1 -1
- package/dist/src/daemon/install-plan.js +2 -2
- package/dist/src/daemon/launchd.js +2 -2
- package/dist/src/daemon/schtasks.js +2 -2
- package/dist/src/daemon/systemd.js +2 -2
- package/dist/src/extensions/bundle-mcp.js +1 -1
- package/dist/src/extensions/discover-extensions.js +1 -1
- package/dist/src/extensions/health.js +1 -1
- package/dist/src/extensions/loader.js +1 -1
- package/dist/src/extensions/lockfile.js +2 -2
- package/dist/src/extensions/update.js +1 -1
- package/dist/src/gateway/agents-admin.js +3 -3
- package/dist/src/gateway/file-path-classifier.js +2 -2
- package/dist/src/gateway/hono/lib/config-payload.js +1 -1
- package/dist/src/gateway/hono/lib/extension-store.js +2 -2
- package/dist/src/gateway/hono/lib/static-ui.js +2 -2
- package/dist/src/gateway/hono/oauth-async.js +36 -3
- package/dist/src/gateway/hono/oauth-async.js.map +1 -1
- package/dist/src/gateway/hono/oauth.js +1 -1
- package/dist/src/gateway/hono/routes/agents.js +1 -1
- package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
- package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
- package/dist/src/gateway/hono/routes/dreaming.js +1 -1
- package/dist/src/gateway/hono/routes/host-fs.js +2 -2
- package/dist/src/gateway/hono/routes/models.js +1 -1
- package/dist/src/gateway/hono/routes/notes.js +9 -22
- package/dist/src/gateway/hono/routes/notes.js.map +1 -1
- package/dist/src/gateway/hono/routes/shares.js +1 -1
- package/dist/src/gateway/hono/routes/workspace.js +2 -2
- package/dist/src/gateway/lock.js +3 -3
- package/dist/src/gateway/ports.js +1 -1
- package/dist/src/gateway/service/agent-runner.js +2 -2
- package/dist/src/gateway/service/marketplace-service.js +2 -2
- package/dist/src/gateway/service.js +1 -1
- package/dist/src/gateway/workspace-fs-file-list.js +1 -1
- package/dist/src/infra/brew.js +1 -1
- package/dist/src/infra/http-proxy-env.d.ts +4 -0
- package/dist/src/infra/http-proxy-env.js +23 -0
- package/dist/src/infra/http-proxy-env.js.map +1 -0
- package/dist/src/infra/package-json.js +1 -1
- package/dist/src/infra/package-update-steps.js +1 -1
- package/dist/src/infra/path-env.js +2 -2
- package/dist/src/infra/restart.js +2 -2
- package/dist/src/infra/stable-node-path.js +1 -1
- package/dist/src/infra/update-check.js +1 -1
- package/dist/src/infra/update-global.js +1 -1
- package/dist/src/infra/update-lock.js +3 -3
- package/dist/src/infra/update-runner.js +1 -1
- package/dist/src/infra/update-startup.js +2 -2
- package/dist/src/infra/write-file-atomic.js +2 -2
- package/dist/src/media/store.js +1 -1
- package/dist/src/notes/note-attachment-sync.d.ts +2 -3
- package/dist/src/notes/note-attachment-sync.js +2 -27
- package/dist/src/notes/note-attachment-sync.js.map +1 -1
- package/dist/src/notes/note-index-meta.d.ts +6 -2
- package/dist/src/notes/note-index-meta.js +11 -16
- package/dist/src/notes/note-index-meta.js.map +1 -1
- package/dist/src/notes/note-markdown.d.ts +61 -0
- package/dist/src/notes/note-markdown.js +177 -0
- package/dist/src/notes/note-markdown.js.map +1 -0
- package/dist/src/notes/service.d.ts +9 -7
- package/dist/src/notes/service.js +163 -312
- package/dist/src/notes/service.js.map +1 -1
- package/dist/src/notes/store.js +4 -5
- package/dist/src/notes/store.js.map +1 -1
- package/dist/src/notes/types.d.ts +29 -58
- package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
- package/dist/src/providers/index.js +2 -2
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/session/init-session-turn.js +2 -2
- package/dist/src/session/resolve-session.js +3 -3
- package/dist/src/session/session-title.js +2 -2
- package/dist/src/session/store.js +2 -2
- package/dist/src/share/share-auto.js +2 -2
- package/dist/src/share/share-store.js +3 -3
- package/dist/src/share/share-thumbnail.js +2 -2
- package/dist/src/share/share-zip.js +1 -1
- package/dist/src/share/site-share-store.js +3 -3
- package/dist/src/share/site-static-serve.js +1 -1
- package/dist/src/storage/sqlite/connection.js +2 -2
- package/dist/src/storage/sqlite/memory-index-repository.js +2 -2
- package/dist/src/storage/sqlite/migrations/003_add_note_markdown_meta.sql +4 -0
- package/dist/src/storage/sqlite/migrations/discover.js +1 -1
- package/dist/src/storage/sqlite/migrations/runner.d.ts +2 -2
- package/dist/src/storage/sqlite/migrations/runner.js +5 -5
- package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
- package/dist/src/storage/sqlite/migrations/runner.ts +2 -2
- package/dist/src/storage/sqlite/notes-repository.js +18 -6
- package/dist/src/storage/sqlite/notes-repository.js.map +1 -1
- package/dist/src/storage/sqlite/schema.js +4 -4
- package/dist/src/storage/sqlite/schema.sql +5 -1
- package/dist/src/tui/clipboard-image.js +3 -3
- package/dist/src/tui/theme-manager.js +1 -1
- package/dist/src/tui/tui-keybindings-file.js +1 -1
- package/dist/src/tui/tui-scoped-models.js +2 -2
- package/dist/src/tui/tui-settings.js +1 -1
- package/dist/src/tui/tui.js +3 -3
- package/dist/src/tunnel/frpc-binary.js +3 -3
- package/dist/src/tunnel/frpc-config.js +1 -1
- package/dist/src/tunnel/frpc-extract.js +1 -1
- package/dist/src/tunnel/tunnel-state.js +1 -1
- package/dist/src/utils/logger/audit.js +1 -1
- package/dist/src/utils/logger/log-store.js +1 -1
- package/dist/src/utils/logger/rotation.js +1 -1
- package/dist/src/voice/tts/audio.js +1 -1
- package/dist/src/voice/tts/providers/edge-speech.js +2 -2
- package/dist/src/workflows/store/event-store.js +1 -1
- package/dist/src/workflows/store/run-store.js +1 -1
- package/package.json +3 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveDefaultAgentId } from "../../../agent/agent-scope.js";
|
|
2
2
|
import { resolveModelsJsonPath } from "../../../config/paths.js";
|
|
3
|
-
import { init_models_json, loadModelsJson } from "../../../config/models-json.js";
|
|
4
3
|
import { CredentialResolver, init_credentials } from "../../../auth/credentials.js";
|
|
4
|
+
import { init_models_json, loadModelsJson } from "../../../config/models-json.js";
|
|
5
5
|
import { getProviderRegistry, init_plugin_registry } from "../../../providers/plugin-registry.js";
|
|
6
6
|
import { getAllProviders, init_providers, isProviderConfigured } from "../../../providers/index.js";
|
|
7
7
|
import { resolveShareConfig } from "../../../share/share-config.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { init_write_file_atomic, writeTextAtomic } from "../../../infra/write-file-atomic.js";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import { join } from "node:path";
|
|
4
2
|
import { readFile } from "node:fs/promises";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
5
|
//#region src/gateway/hono/lib/extension-store.ts
|
|
6
6
|
init_write_file_atomic();
|
|
7
7
|
/** Extension UI: write-through JSON KV per namespace under ~/.xopc/extensions/{namespace}/storage.json */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { dirname, resolve } from "node:path";
|
|
2
|
-
import { readFileSync } from "node:fs";
|
|
3
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath } from "node:url";
|
|
5
5
|
//#region src/gateway/hono/lib/static-ui.ts
|
|
6
6
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -2,6 +2,8 @@ import { createLogger } from "../../utils/logger/index.js";
|
|
|
2
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
3
|
import { CredentialResolver, init_credentials } from "../../auth/credentials.js";
|
|
4
4
|
import { anthropicOAuthProvider } from "../../auth/oauth/anthropic.js";
|
|
5
|
+
import { isLoopbackHost } from "../host.js";
|
|
6
|
+
import { resolveReverseProxyPublicUrl } from "../public-url.js";
|
|
5
7
|
import { minimaxOAuthProvider } from "../../auth/oauth/minimax.js";
|
|
6
8
|
import { minimaxCnOAuthProvider } from "../../auth/oauth/minimax-cn.js";
|
|
7
9
|
import { kimiCodingOAuthProvider } from "../../auth/oauth/kimi-coding.js";
|
|
@@ -19,8 +21,8 @@ import { Hono } from "hono";
|
|
|
19
21
|
* This allows OAuth flows that require user interaction (browser login)
|
|
20
22
|
* without blocking the HTTP request.
|
|
21
23
|
*/
|
|
22
|
-
init_logger();
|
|
23
24
|
init_credentials();
|
|
25
|
+
init_logger();
|
|
24
26
|
const log = createLogger("OAuthAsync");
|
|
25
27
|
/** User-facing message when undici/fetch fails (often DNS, firewall, or wrong machine for localhost callback). */
|
|
26
28
|
function formatOAuthAsyncError(err) {
|
|
@@ -61,6 +63,29 @@ function cancelOAuthSession(session, message = "OAuth flow cancelled") {
|
|
|
61
63
|
session.status = "cancelled";
|
|
62
64
|
session.message = message;
|
|
63
65
|
}
|
|
66
|
+
function hostWithoutPort(value) {
|
|
67
|
+
const raw = value?.split(",")[0]?.trim();
|
|
68
|
+
if (!raw) return void 0;
|
|
69
|
+
try {
|
|
70
|
+
return new URL(raw.includes("://") ? raw : `http://${raw}`).hostname.replace(/^\[/, "").replace(/\]$/, "");
|
|
71
|
+
} catch {
|
|
72
|
+
const unbracketed = raw.replace(/^\[/, "").replace(/\]$/, "");
|
|
73
|
+
return unbracketed.includes(":") && !unbracketed.includes(".") ? unbracketed : unbracketed.split(":")[0];
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function requestLooksRemote(c) {
|
|
77
|
+
return [
|
|
78
|
+
hostWithoutPort(c.req.header("origin")),
|
|
79
|
+
hostWithoutPort(c.req.header("x-forwarded-host")),
|
|
80
|
+
hostWithoutPort(c.req.header("host"))
|
|
81
|
+
].some((candidate) => candidate && !isLoopbackHost(candidate));
|
|
82
|
+
}
|
|
83
|
+
function preferredOAuthLoginMethod(params) {
|
|
84
|
+
if (typeof params.requestedMethod === "string" && params.requestedMethod.trim()) return params.requestedMethod.trim();
|
|
85
|
+
if (params.provider !== "openai-codex") return;
|
|
86
|
+
const publicHost = hostWithoutPort(resolveReverseProxyPublicUrl(params.service.currentConfig) ?? void 0);
|
|
87
|
+
if (publicHost && !isLoopbackHost(publicHost) || requestLooksRemote(params.c)) return "device_code";
|
|
88
|
+
}
|
|
64
89
|
function createOAuthAsyncHandler(service) {
|
|
65
90
|
const oauth = new Hono();
|
|
66
91
|
/**
|
|
@@ -68,7 +93,8 @@ function createOAuthAsyncHandler(service) {
|
|
|
68
93
|
* Start async OAuth flow - returns immediately with session ID
|
|
69
94
|
*/
|
|
70
95
|
oauth.post("/start", async (c) => {
|
|
71
|
-
const
|
|
96
|
+
const body = await c.req.json().catch(() => ({}));
|
|
97
|
+
const { provider } = body;
|
|
72
98
|
if (!provider) return c.json({ error: "Provider is required" }, 400);
|
|
73
99
|
const oauthProvider = OAUTH_PROVIDERS[provider];
|
|
74
100
|
if (!oauthProvider) return c.json({ error: `Unknown OAuth provider: ${provider}` }, 400);
|
|
@@ -76,6 +102,12 @@ function createOAuthAsyncHandler(service) {
|
|
|
76
102
|
const session = {
|
|
77
103
|
id: sessionId,
|
|
78
104
|
provider,
|
|
105
|
+
preferredLoginMethod: preferredOAuthLoginMethod({
|
|
106
|
+
provider,
|
|
107
|
+
requestedMethod: body.loginMethod,
|
|
108
|
+
c,
|
|
109
|
+
service
|
|
110
|
+
}),
|
|
79
111
|
status: "pending",
|
|
80
112
|
createdAt: Date.now(),
|
|
81
113
|
expiresAt: Date.now() + SESSION_TTL_MS
|
|
@@ -230,9 +262,10 @@ async function runOAuthFlow(session, oauthProvider, _service) {
|
|
|
230
262
|
return "";
|
|
231
263
|
},
|
|
232
264
|
onSelect: async (prompt) => {
|
|
265
|
+
const preferredOption = session.preferredLoginMethod ? prompt.options.find((option) => option.id === session.preferredLoginMethod) : void 0;
|
|
233
266
|
const browserOption = prompt.options.find((option) => option.id === "browser");
|
|
234
267
|
const firstOption = prompt.options[0];
|
|
235
|
-
const selectedOption = browserOption ?? firstOption;
|
|
268
|
+
const selectedOption = preferredOption ?? browserOption ?? firstOption;
|
|
236
269
|
if (!selectedOption) throw new Error("OAuth login did not provide any selectable auth method");
|
|
237
270
|
log.debug({
|
|
238
271
|
sessionId: session.id,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-async.js","names":["googleGeminiCliOAuthProvider","googleAntigravityOAuthProvider"],"sources":["../../../../src/gateway/hono/oauth-async.ts"],"sourcesContent":["/**\n * Async OAuth Handler\n * \n * Provides non-blocking OAuth flow with session-based state management.\n * This allows OAuth flows that require user interaction (browser login) \n * without blocking the HTTP request.\n */\n\nimport { Hono } from 'hono';\nimport type { GatewayService } from '../service.js';\nimport { \n type OAuthProviderInterface, \n type OAuthLoginCallbacks,\n type OAuthCredentials \n} from '../../auth/oauth/types.js';\nimport {\n kimiCodingOAuthProvider,\n minimaxOAuthProvider,\n minimaxCnOAuthProvider,\n anthropicOAuthProvider,\n githubCopilotOAuthProvider,\n googleGeminiCliOAuthProvider,\n googleAntigravityOAuthProvider,\n openaiCodexOAuthProvider,\n} from '../../auth/oauth/index.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { CredentialResolver } from '../../auth/credentials.js';\n\nconst log = createLogger('OAuthAsync');\n\n/** User-facing message when undici/fetch fails (often DNS, firewall, or wrong machine for localhost callback). */\nfunction formatOAuthAsyncError(err: unknown): string {\n\tconst base = err instanceof Error ? err.message : 'OAuth login failed';\n\tconst cause =\n\t\terr instanceof Error && err.cause instanceof Error\n\t\t\t? err.cause.message\n\t\t\t: err instanceof Error && typeof err.cause === 'string'\n\t\t\t\t? err.cause\n\t\t\t\t: '';\n\tconst detail = cause ? ` (${cause})` : '';\n\tif (/^fetch failed$/i.test(base) || base.includes('fetch failed')) {\n\t\treturn (\n\t\t\t`Network request failed${detail}. If the browser opened on another device, the redirect goes to that device's localhost — ` +\n\t\t\t`copy the full URL from the browser address bar after sign-in (starts with http://127.0.0.1 or http://localhost) and paste it below. ` +\n\t\t\t`Otherwise check VPN/proxy/DNS/firewall access to Google OAuth.`\n\t\t);\n\t}\n\treturn base;\n}\n\n// Static OAuth providers map\nconst OAUTH_PROVIDERS: Record<string, OAuthProviderInterface> = {\n 'kimi-coding': kimiCodingOAuthProvider,\n 'minimax': minimaxOAuthProvider,\n 'minimax-cn': minimaxCnOAuthProvider,\n 'anthropic': anthropicOAuthProvider,\n 'github-copilot': githubCopilotOAuthProvider,\n 'google-gemini-cli': googleGeminiCliOAuthProvider,\n 'google-antigravity': googleAntigravityOAuthProvider,\n 'openai-codex': openaiCodexOAuthProvider,\n};\n\n// OAuth session state\ninterface OAuthSession {\n id: string;\n provider: string;\n status: 'pending' | 'waiting_auth' | 'waiting_code' | 'completed' | 'failed' | 'cancelled';\n authUrl?: string;\n instructions?: string;\n deviceCode?: string;\n verificationUri?: string;\n message?: string;\n error?: string;\n credentials?: OAuthCredentials;\n createdAt: number;\n expiresAt: number;\n abortController?: AbortController;\n manualCodeResolve?: (code: string) => void;\n manualCodeReject?: (error: Error) => void;\n}\n\n// In-memory session store (could be moved to Redis for production)\nconst oauthSessions = new Map<string, OAuthSession>();\nconst SESSION_TTL_MS = 10 * 60 * 1000; // 10 minutes\n\n// Clean up expired sessions periodically\nsetInterval(() => {\n const now = Date.now();\n for (const [id, session] of oauthSessions.entries()) {\n if (now > session.expiresAt) {\n cancelOAuthSession(session, 'OAuth flow expired');\n oauthSessions.delete(id);\n log.debug({ sessionId: id }, 'Cleaned up expired OAuth session');\n }\n }\n}, 60 * 1000);\n\nfunction generateSessionId(): string {\n return `oauth_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;\n}\n\nfunction cancelOAuthSession(session: OAuthSession, message = 'OAuth flow cancelled'): void {\n if (session.abortController) {\n session.abortController.abort();\n }\n\n if (session.manualCodeResolve) {\n session.manualCodeResolve('');\n }\n\n session.manualCodeResolve = undefined;\n session.manualCodeReject = undefined;\n session.status = 'cancelled';\n session.message = message;\n}\n\nexport function createOAuthAsyncHandler(service: GatewayService) {\n const oauth = new Hono();\n\n /**\n * POST /api/auth/oauth-async/start\n * Start async OAuth flow - returns immediately with session ID\n */\n oauth.post('/start', async (c) => {\n const { provider } = await c.req.json().catch(() => ({}));\n \n if (!provider) {\n return c.json({ error: 'Provider is required' }, 400);\n }\n\n const oauthProvider = OAUTH_PROVIDERS[provider];\n if (!oauthProvider) {\n return c.json({ error: `Unknown OAuth provider: ${provider}` }, 400);\n }\n\n const sessionId = generateSessionId();\n const session: OAuthSession = {\n id: sessionId,\n provider,\n status: 'pending',\n createdAt: Date.now(),\n expiresAt: Date.now() + SESSION_TTL_MS,\n };\n\n oauthSessions.set(sessionId, session);\n\n // Start OAuth flow in background\n runOAuthFlow(session, oauthProvider, service).catch(err => {\n log.error({ sessionId, provider, error: err }, 'Background OAuth flow failed');\n session.status = 'failed';\n session.error = err instanceof Error ? err.message : 'OAuth flow failed';\n });\n\n return c.json({ \n ok: true, \n payload: { \n sessionId,\n provider,\n status: session.status,\n } \n });\n });\n\n /**\n * GET /api/auth/oauth-async/:sessionId/status\n * Check OAuth session status\n */\n oauth.get('/:sessionId/status', (c) => {\n const sessionId = c.req.param('sessionId');\n const session = oauthSessions.get(sessionId);\n\n if (!session) {\n return c.json({ error: 'Session not found' }, 404);\n }\n\n return c.json({ \n ok: true, \n payload: { \n sessionId: session.id,\n provider: session.provider,\n status: session.status,\n authUrl: session.authUrl,\n instructions: session.instructions,\n deviceCode: session.deviceCode,\n verificationUri: session.verificationUri,\n message: session.message,\n error: session.error,\n expiresAt: session.expiresAt,\n } \n });\n });\n\n /**\n * POST /api/auth/oauth-async/:sessionId/code\n * Submit manual authorization code\n */\n oauth.post('/:sessionId/code', async (c) => {\n const sessionId = c.req.param('sessionId');\n const { code } = await c.req.json().catch(() => ({}));\n \n if (!code) {\n return c.json({ error: 'Code is required' }, 400);\n }\n\n const session = oauthSessions.get(sessionId);\n if (!session) {\n return c.json({ error: 'Session not found' }, 404);\n }\n\n if (session.status !== 'waiting_code' || !session.manualCodeResolve) {\n return c.json({ error: 'Session is not waiting for code' }, 400);\n }\n\n // Resolve the manual code promise\n session.manualCodeResolve(code);\n session.manualCodeResolve = undefined;\n session.manualCodeReject = undefined;\n\n return c.json({ \n ok: true, \n payload: { \n message: 'Code submitted, processing...',\n } \n });\n });\n\n /**\n * POST /api/auth/oauth-async/:sessionId/cancel\n * Cancel OAuth flow\n */\n oauth.post('/:sessionId/cancel', async (c) => {\n const sessionId = c.req.param('sessionId');\n const session = oauthSessions.get(sessionId);\n\n if (!session) {\n return c.json({ error: 'Session not found' }, 404);\n }\n\n cancelOAuthSession(session);\n\n return c.json({ \n ok: true, \n payload: { \n message: 'OAuth flow cancelled',\n } \n });\n });\n\n /**\n * DELETE /api/auth/oauth-async/:sessionId\n * Clean up OAuth session\n */\n oauth.delete('/:sessionId', (c) => {\n const sessionId = c.req.param('sessionId');\n \n if (oauthSessions.has(sessionId)) {\n const session = oauthSessions.get(sessionId)!;\n cancelOAuthSession(session);\n oauthSessions.delete(sessionId);\n }\n\n return c.json({ ok: true });\n });\n\n return oauth;\n}\n\n/**\n * Run OAuth flow in background\n */\nasync function runOAuthFlow(\n session: OAuthSession,\n oauthProvider: OAuthProviderInterface,\n _service: GatewayService\n): Promise<void> {\n const abortController = new AbortController();\n session.abortController = abortController;\n\n let manualCodePromise: Promise<string> | null = null;\n let manualCodeResolve: ((code: string) => void) | undefined;\n let manualCodeReject: ((error: Error) => void) | undefined;\n\n const callbacks: OAuthLoginCallbacks = {\n onAuth: (auth: { url: string; instructions?: string }) => {\n session.authUrl = auth.url;\n session.instructions = auth.instructions;\n \n if (oauthProvider.usesCallbackServer) {\n // For callback server providers, prepare for manual code input\n session.status = 'waiting_code';\n session.message = 'Complete authorization in browser, or paste the redirect URL below';\n manualCodePromise = new Promise((resolve, reject) => {\n manualCodeResolve = resolve;\n manualCodeReject = reject;\n });\n session.manualCodeResolve = manualCodeResolve;\n session.manualCodeReject = manualCodeReject;\n } else {\n session.status = 'waiting_auth';\n session.message = 'Complete authorization in browser';\n }\n },\n onDeviceCode: (info) => {\n session.status = 'waiting_auth';\n session.authUrl = info.verificationUri;\n session.deviceCode = info.userCode;\n session.verificationUri = info.verificationUri;\n session.instructions = `Enter code ${info.userCode}`;\n session.message = `Open ${info.verificationUri} and enter code ${info.userCode}`;\n },\n onPrompt: async (prompt: { message: string; deviceCode?: string; verificationUri?: string }) => {\n session.status = 'waiting_code';\n session.deviceCode = prompt.deviceCode;\n session.verificationUri = prompt.verificationUri;\n session.message = prompt.message;\n \n // For device code flow, wait for manual input\n manualCodePromise = new Promise((resolve, reject) => {\n manualCodeResolve = resolve;\n manualCodeReject = reject;\n });\n session.manualCodeResolve = manualCodeResolve;\n session.manualCodeReject = manualCodeReject;\n \n // Return empty for now, will be resolved by manual code submission\n return '';\n },\n onProgress: (message: string) => {\n log.debug({ sessionId: session.id, message }, 'OAuth progress');\n session.message = message;\n },\n onManualCodeInput: async () => {\n // Return the manual code promise for callback server providers\n if (manualCodePromise) {\n return manualCodePromise;\n }\n return '';\n },\n onSelect: async (prompt) => {\n const browserOption = prompt.options.find((option) => option.id === 'browser');\n const firstOption = prompt.options[0];\n const selectedOption = browserOption ?? firstOption;\n if (!selectedOption) {\n throw new Error('OAuth login did not provide any selectable auth method');\n }\n log.debug(\n { sessionId: session.id, provider: session.provider, selected: selectedOption.id },\n 'Selected OAuth auth method',\n );\n return selectedOption.id;\n },\n signal: abortController.signal,\n };\n\n try {\n const credentials = await oauthProvider.login(callbacks);\n \n // Save credentials to cache and persist them as first-class OAuth credentials.\n setOAuthCredentialsToCache(session.provider, credentials);\n\n const resolver = new CredentialResolver();\n await resolver.saveOAuthToken(session.provider, {\n access: oauthProvider.getApiKey(credentials),\n refresh: credentials.refresh,\n expiresAt: credentials.expires,\n scope: Array.isArray(credentials.scope) ? credentials.scope.filter((value): value is string => typeof value === 'string') : undefined,\n createdAt: new Date().toISOString(),\n });\n\n session.status = 'completed';\n session.credentials = credentials;\n session.message = 'OAuth login successful';\n \n log.info({ sessionId: session.id, provider: session.provider }, 'OAuth login completed');\n } catch (err) {\n if (abortController.signal.aborted || session.status === 'cancelled') {\n session.status = 'cancelled';\n session.message ??= 'OAuth flow cancelled by user';\n } else {\n session.status = 'failed';\n session.error = formatOAuthAsyncError(err);\n log.error({ sessionId: session.id, provider: session.provider, error: err }, 'OAuth login failed');\n }\n } finally {\n session.abortController = undefined;\n session.manualCodeResolve = undefined;\n session.manualCodeReject = undefined;\n }\n}\n\n// Simple in-memory cache for OAuth credentials\nconst oauthCredentialsCache: Map<string, OAuthCredentials> = new Map();\n\nexport function getOAuthCredentialsFromCache(provider: string): OAuthCredentials | undefined {\n return oauthCredentialsCache.get(provider);\n}\n\nexport function setOAuthCredentialsToCache(provider: string, creds: OAuthCredentials): void {\n oauthCredentialsCache.set(provider, creds);\n}\n\nexport function deleteOAuthCredentialsFromCache(provider: string): void {\n oauthCredentialsCache.delete(provider);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"oauth-async.js","names":["googleGeminiCliOAuthProvider","googleAntigravityOAuthProvider"],"sources":["../../../../src/gateway/hono/oauth-async.ts"],"sourcesContent":["/**\n * Async OAuth Handler\n * \n * Provides non-blocking OAuth flow with session-based state management.\n * This allows OAuth flows that require user interaction (browser login) \n * without blocking the HTTP request.\n */\n\nimport { Hono } from 'hono';\nimport type { Context } from 'hono';\nimport type { GatewayService } from '../service.js';\nimport { \n type OAuthProviderInterface, \n type OAuthLoginCallbacks,\n type OAuthCredentials \n} from '../../auth/oauth/types.js';\nimport {\n kimiCodingOAuthProvider,\n minimaxOAuthProvider,\n minimaxCnOAuthProvider,\n anthropicOAuthProvider,\n githubCopilotOAuthProvider,\n googleGeminiCliOAuthProvider,\n googleAntigravityOAuthProvider,\n openaiCodexOAuthProvider,\n} from '../../auth/oauth/index.js';\nimport { CredentialResolver } from '../../auth/credentials.js';\nimport { isLoopbackHost } from '../host.js';\nimport { resolveReverseProxyPublicUrl } from '../public-url.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('OAuthAsync');\n\n/** User-facing message when undici/fetch fails (often DNS, firewall, or wrong machine for localhost callback). */\nfunction formatOAuthAsyncError(err: unknown): string {\n\tconst base = err instanceof Error ? err.message : 'OAuth login failed';\n\tconst cause =\n\t\terr instanceof Error && err.cause instanceof Error\n\t\t\t? err.cause.message\n\t\t\t: err instanceof Error && typeof err.cause === 'string'\n\t\t\t\t? err.cause\n\t\t\t\t: '';\n\tconst detail = cause ? ` (${cause})` : '';\n\tif (/^fetch failed$/i.test(base) || base.includes('fetch failed')) {\n\t\treturn (\n\t\t\t`Network request failed${detail}. If the browser opened on another device, the redirect goes to that device's localhost — ` +\n\t\t\t`copy the full URL from the browser address bar after sign-in (starts with http://127.0.0.1 or http://localhost) and paste it below. ` +\n\t\t\t`Otherwise check VPN/proxy/DNS/firewall access to Google OAuth.`\n\t\t);\n\t}\n\treturn base;\n}\n\n// Static OAuth providers map\nconst OAUTH_PROVIDERS: Record<string, OAuthProviderInterface> = {\n 'kimi-coding': kimiCodingOAuthProvider,\n 'minimax': minimaxOAuthProvider,\n 'minimax-cn': minimaxCnOAuthProvider,\n 'anthropic': anthropicOAuthProvider,\n 'github-copilot': githubCopilotOAuthProvider,\n 'google-gemini-cli': googleGeminiCliOAuthProvider,\n 'google-antigravity': googleAntigravityOAuthProvider,\n 'openai-codex': openaiCodexOAuthProvider,\n};\n\n// OAuth session state\ninterface OAuthSession {\n id: string;\n provider: string;\n preferredLoginMethod?: string;\n status: 'pending' | 'waiting_auth' | 'waiting_code' | 'completed' | 'failed' | 'cancelled';\n authUrl?: string;\n instructions?: string;\n deviceCode?: string;\n verificationUri?: string;\n message?: string;\n error?: string;\n credentials?: OAuthCredentials;\n createdAt: number;\n expiresAt: number;\n abortController?: AbortController;\n manualCodeResolve?: (code: string) => void;\n manualCodeReject?: (error: Error) => void;\n}\n\n// In-memory session store (could be moved to Redis for production)\nconst oauthSessions = new Map<string, OAuthSession>();\nconst SESSION_TTL_MS = 10 * 60 * 1000; // 10 minutes\n\n// Clean up expired sessions periodically\nsetInterval(() => {\n const now = Date.now();\n for (const [id, session] of oauthSessions.entries()) {\n if (now > session.expiresAt) {\n cancelOAuthSession(session, 'OAuth flow expired');\n oauthSessions.delete(id);\n log.debug({ sessionId: id }, 'Cleaned up expired OAuth session');\n }\n }\n}, 60 * 1000);\n\nfunction generateSessionId(): string {\n return `oauth_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;\n}\n\nfunction cancelOAuthSession(session: OAuthSession, message = 'OAuth flow cancelled'): void {\n if (session.abortController) {\n session.abortController.abort();\n }\n\n if (session.manualCodeResolve) {\n session.manualCodeResolve('');\n }\n\n session.manualCodeResolve = undefined;\n session.manualCodeReject = undefined;\n session.status = 'cancelled';\n session.message = message;\n}\n\nfunction hostWithoutPort(value: string | undefined): string | undefined {\n const raw = value?.split(',')[0]?.trim();\n if (!raw) return undefined;\n\n try {\n return new URL(raw.includes('://') ? raw : `http://${raw}`).hostname.replace(/^\\[/, '').replace(/\\]$/, '');\n } catch {\n const unbracketed = raw.replace(/^\\[/, '').replace(/\\]$/, '');\n return unbracketed.includes(':') && !unbracketed.includes('.') ? unbracketed : unbracketed.split(':')[0];\n }\n}\n\nfunction requestLooksRemote(c: Context): boolean {\n const originHost = hostWithoutPort(c.req.header('origin'));\n const forwardedHost = hostWithoutPort(c.req.header('x-forwarded-host'));\n const host = hostWithoutPort(c.req.header('host'));\n\n return [originHost, forwardedHost, host].some((candidate) => candidate && !isLoopbackHost(candidate));\n}\n\nfunction preferredOAuthLoginMethod(params: {\n provider: string;\n requestedMethod?: unknown;\n c: Context;\n service: GatewayService;\n}): string | undefined {\n if (typeof params.requestedMethod === 'string' && params.requestedMethod.trim()) {\n return params.requestedMethod.trim();\n }\n\n if (params.provider !== 'openai-codex') {\n return undefined;\n }\n\n const publicUrl = resolveReverseProxyPublicUrl(params.service.currentConfig);\n const publicHost = hostWithoutPort(publicUrl ?? undefined);\n if ((publicHost && !isLoopbackHost(publicHost)) || requestLooksRemote(params.c)) {\n return 'device_code';\n }\n\n return undefined;\n}\n\nexport function createOAuthAsyncHandler(service: GatewayService) {\n const oauth = new Hono();\n\n /**\n * POST /api/auth/oauth-async/start\n * Start async OAuth flow - returns immediately with session ID\n */\n oauth.post('/start', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const { provider } = body;\n \n if (!provider) {\n return c.json({ error: 'Provider is required' }, 400);\n }\n\n const oauthProvider = OAUTH_PROVIDERS[provider];\n if (!oauthProvider) {\n return c.json({ error: `Unknown OAuth provider: ${provider}` }, 400);\n }\n\n const sessionId = generateSessionId();\n const session: OAuthSession = {\n id: sessionId,\n provider,\n preferredLoginMethod: preferredOAuthLoginMethod({\n provider,\n requestedMethod: body.loginMethod,\n c,\n service,\n }),\n status: 'pending',\n createdAt: Date.now(),\n expiresAt: Date.now() + SESSION_TTL_MS,\n };\n\n oauthSessions.set(sessionId, session);\n\n // Start OAuth flow in background\n runOAuthFlow(session, oauthProvider, service).catch(err => {\n log.error({ sessionId, provider, error: err }, 'Background OAuth flow failed');\n session.status = 'failed';\n session.error = err instanceof Error ? err.message : 'OAuth flow failed';\n });\n\n return c.json({ \n ok: true, \n payload: { \n sessionId,\n provider,\n status: session.status,\n } \n });\n });\n\n /**\n * GET /api/auth/oauth-async/:sessionId/status\n * Check OAuth session status\n */\n oauth.get('/:sessionId/status', (c) => {\n const sessionId = c.req.param('sessionId');\n const session = oauthSessions.get(sessionId);\n\n if (!session) {\n return c.json({ error: 'Session not found' }, 404);\n }\n\n return c.json({ \n ok: true, \n payload: { \n sessionId: session.id,\n provider: session.provider,\n status: session.status,\n authUrl: session.authUrl,\n instructions: session.instructions,\n deviceCode: session.deviceCode,\n verificationUri: session.verificationUri,\n message: session.message,\n error: session.error,\n expiresAt: session.expiresAt,\n } \n });\n });\n\n /**\n * POST /api/auth/oauth-async/:sessionId/code\n * Submit manual authorization code\n */\n oauth.post('/:sessionId/code', async (c) => {\n const sessionId = c.req.param('sessionId');\n const { code } = await c.req.json().catch(() => ({}));\n \n if (!code) {\n return c.json({ error: 'Code is required' }, 400);\n }\n\n const session = oauthSessions.get(sessionId);\n if (!session) {\n return c.json({ error: 'Session not found' }, 404);\n }\n\n if (session.status !== 'waiting_code' || !session.manualCodeResolve) {\n return c.json({ error: 'Session is not waiting for code' }, 400);\n }\n\n // Resolve the manual code promise\n session.manualCodeResolve(code);\n session.manualCodeResolve = undefined;\n session.manualCodeReject = undefined;\n\n return c.json({ \n ok: true, \n payload: { \n message: 'Code submitted, processing...',\n } \n });\n });\n\n /**\n * POST /api/auth/oauth-async/:sessionId/cancel\n * Cancel OAuth flow\n */\n oauth.post('/:sessionId/cancel', async (c) => {\n const sessionId = c.req.param('sessionId');\n const session = oauthSessions.get(sessionId);\n\n if (!session) {\n return c.json({ error: 'Session not found' }, 404);\n }\n\n cancelOAuthSession(session);\n\n return c.json({ \n ok: true, \n payload: { \n message: 'OAuth flow cancelled',\n } \n });\n });\n\n /**\n * DELETE /api/auth/oauth-async/:sessionId\n * Clean up OAuth session\n */\n oauth.delete('/:sessionId', (c) => {\n const sessionId = c.req.param('sessionId');\n \n if (oauthSessions.has(sessionId)) {\n const session = oauthSessions.get(sessionId)!;\n cancelOAuthSession(session);\n oauthSessions.delete(sessionId);\n }\n\n return c.json({ ok: true });\n });\n\n return oauth;\n}\n\n/**\n * Run OAuth flow in background\n */\nasync function runOAuthFlow(\n session: OAuthSession,\n oauthProvider: OAuthProviderInterface,\n _service: GatewayService\n): Promise<void> {\n const abortController = new AbortController();\n session.abortController = abortController;\n\n let manualCodePromise: Promise<string> | null = null;\n let manualCodeResolve: ((code: string) => void) | undefined;\n let manualCodeReject: ((error: Error) => void) | undefined;\n\n const callbacks: OAuthLoginCallbacks = {\n onAuth: (auth: { url: string; instructions?: string }) => {\n session.authUrl = auth.url;\n session.instructions = auth.instructions;\n \n if (oauthProvider.usesCallbackServer) {\n // For callback server providers, prepare for manual code input\n session.status = 'waiting_code';\n session.message = 'Complete authorization in browser, or paste the redirect URL below';\n manualCodePromise = new Promise((resolve, reject) => {\n manualCodeResolve = resolve;\n manualCodeReject = reject;\n });\n session.manualCodeResolve = manualCodeResolve;\n session.manualCodeReject = manualCodeReject;\n } else {\n session.status = 'waiting_auth';\n session.message = 'Complete authorization in browser';\n }\n },\n onDeviceCode: (info) => {\n session.status = 'waiting_auth';\n session.authUrl = info.verificationUri;\n session.deviceCode = info.userCode;\n session.verificationUri = info.verificationUri;\n session.instructions = `Enter code ${info.userCode}`;\n session.message = `Open ${info.verificationUri} and enter code ${info.userCode}`;\n },\n onPrompt: async (prompt: { message: string; deviceCode?: string; verificationUri?: string }) => {\n session.status = 'waiting_code';\n session.deviceCode = prompt.deviceCode;\n session.verificationUri = prompt.verificationUri;\n session.message = prompt.message;\n \n // For device code flow, wait for manual input\n manualCodePromise = new Promise((resolve, reject) => {\n manualCodeResolve = resolve;\n manualCodeReject = reject;\n });\n session.manualCodeResolve = manualCodeResolve;\n session.manualCodeReject = manualCodeReject;\n \n // Return empty for now, will be resolved by manual code submission\n return '';\n },\n onProgress: (message: string) => {\n log.debug({ sessionId: session.id, message }, 'OAuth progress');\n session.message = message;\n },\n onManualCodeInput: async () => {\n // Return the manual code promise for callback server providers\n if (manualCodePromise) {\n return manualCodePromise;\n }\n return '';\n },\n onSelect: async (prompt) => {\n const preferredOption = session.preferredLoginMethod\n ? prompt.options.find((option) => option.id === session.preferredLoginMethod)\n : undefined;\n const browserOption = prompt.options.find((option) => option.id === 'browser');\n const firstOption = prompt.options[0];\n const selectedOption = preferredOption ?? browserOption ?? firstOption;\n if (!selectedOption) {\n throw new Error('OAuth login did not provide any selectable auth method');\n }\n log.debug(\n { sessionId: session.id, provider: session.provider, selected: selectedOption.id },\n 'Selected OAuth auth method',\n );\n return selectedOption.id;\n },\n signal: abortController.signal,\n };\n\n try {\n const credentials = await oauthProvider.login(callbacks);\n \n // Save credentials to cache and persist them as first-class OAuth credentials.\n setOAuthCredentialsToCache(session.provider, credentials);\n\n const resolver = new CredentialResolver();\n await resolver.saveOAuthToken(session.provider, {\n access: oauthProvider.getApiKey(credentials),\n refresh: credentials.refresh,\n expiresAt: credentials.expires,\n scope: Array.isArray(credentials.scope) ? credentials.scope.filter((value): value is string => typeof value === 'string') : undefined,\n createdAt: new Date().toISOString(),\n });\n\n session.status = 'completed';\n session.credentials = credentials;\n session.message = 'OAuth login successful';\n \n log.info({ sessionId: session.id, provider: session.provider }, 'OAuth login completed');\n } catch (err) {\n if (abortController.signal.aborted || session.status === 'cancelled') {\n session.status = 'cancelled';\n session.message ??= 'OAuth flow cancelled by user';\n } else {\n session.status = 'failed';\n session.error = formatOAuthAsyncError(err);\n log.error({ sessionId: session.id, provider: session.provider, error: err }, 'OAuth login failed');\n }\n } finally {\n session.abortController = undefined;\n session.manualCodeResolve = undefined;\n session.manualCodeReject = undefined;\n }\n}\n\n// Simple in-memory cache for OAuth credentials\nconst oauthCredentialsCache: Map<string, OAuthCredentials> = new Map();\n\nexport function getOAuthCredentialsFromCache(provider: string): OAuthCredentials | undefined {\n return oauthCredentialsCache.get(provider);\n}\n\nexport function setOAuthCredentialsToCache(provider: string, creds: OAuthCredentials): void {\n oauthCredentialsCache.set(provider, creds);\n}\n\nexport function deleteOAuthCredentialsFromCache(provider: string): void {\n oauthCredentialsCache.delete(provider);\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CredentialResolver, init_credentials } from "../../auth/credentials.js";
|
|
2
|
-
import { getProviderAuthState, init_providers, isProviderConfigured } from "../../providers/index.js";
|
|
3
2
|
import { anthropicOAuthProvider } from "../../auth/oauth/anthropic.js";
|
|
3
|
+
import { getProviderAuthState, init_providers, isProviderConfigured } from "../../providers/index.js";
|
|
4
4
|
import { minimaxOAuthProvider } from "../../auth/oauth/minimax.js";
|
|
5
5
|
import { minimaxCnOAuthProvider } from "../../auth/oauth/minimax-cn.js";
|
|
6
6
|
import { kimiCodingOAuthProvider } from "../../auth/oauth/kimi-coding.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { init_agent_scope, normalizeAgentId } from "../../../agent/agent-scope.js";
|
|
1
2
|
import { init_localized_text, normalizeLocalizedText } from "../../../config/localized-text.js";
|
|
2
3
|
import { init_schema, parseModelRef } from "../../../config/schema.js";
|
|
3
|
-
import { init_agent_scope, normalizeAgentId } from "../../../agent/agent-scope.js";
|
|
4
4
|
import { init_providers, isProviderConfigured, resolveModel } from "../../../providers/index.js";
|
|
5
5
|
import { getVoiceModelsConfig } from "../../../config/voice.js";
|
|
6
6
|
import { deleteAgentAvatarFile, finalizeCreateAgentDirs, listAgentProfileFiles, listGatewayAgents, prepareCreateAgent, prepareCreateAgentsBatch, prepareDeleteAgent, prepareUpdateAgent, readAgentAvatarFile, readAgentProfileFile, runAfterDeletePurge, writeAgentAvatarFromBase64, writeAgentProfileFile } from "../../agents-admin.js";
|
|
@@ -7,8 +7,8 @@ import { createOAuthHandler } from "../oauth.js";
|
|
|
7
7
|
import { createOAuthAsyncHandler } from "../oauth-async.js";
|
|
8
8
|
import { extensionAssetMimeType } from "../lib/extension-assets.js";
|
|
9
9
|
import { loadExtensionStore, saveExtensionStore } from "../lib/extension-store.js";
|
|
10
|
-
import { relative, resolve } from "node:path";
|
|
11
10
|
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
11
|
+
import { relative, resolve } from "node:path";
|
|
12
12
|
//#region src/gateway/hono/routes/auth-registry-extensions.ts
|
|
13
13
|
init_providers();
|
|
14
14
|
const EXTENSION_ASSET_CSP = "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob:; connect-src 'none'; frame-ancestors 'self'; frame-src 'none'; base-uri 'none'; object-src 'none'; form-action 'none'";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { BindingsConfigSchema, McpConfigSchema, init_schema } from "../../../../config/schema.js";
|
|
2
1
|
import { CredentialResolver, init_credentials } from "../../../../auth/credentials.js";
|
|
2
|
+
import { BindingsConfigSchema, McpConfigSchema, init_schema } from "../../../../config/schema.js";
|
|
3
3
|
import { canonicalizeConfiguredMcpServer } from "../../../../config/mcp-config-normalize.js";
|
|
4
4
|
import { mergeCronConfigPatch, mergeGatewaySkillsMarketplacePatch, mergeGoalsConfigPatch, mergeSessionConfigPatch, mergeUpdateConfigPatch } from "../../../../config/web-patch.js";
|
|
5
5
|
import { assertGatewayAuthConfigured, resolveGatewayAuth } from "../../../auth.js";
|
|
@@ -5,8 +5,8 @@ import { getWorkspacePath } from "../../../config/workspace-path-helpers.js";
|
|
|
5
5
|
import { parseDreamingLastRunFile } from "../../../agent/memory/dreaming/last-run.js";
|
|
6
6
|
import { readDreamingEvents } from "../../../agent/memory/dreaming/events.js";
|
|
7
7
|
import { previewDreamingDeepPromotion } from "../../../agent/memory/dreaming/preview.js";
|
|
8
|
-
import path from "node:path";
|
|
9
8
|
import fs from "node:fs/promises";
|
|
9
|
+
import path from "node:path";
|
|
10
10
|
//#region src/gateway/hono/routes/dreaming.ts
|
|
11
11
|
function isRecord(v) {
|
|
12
12
|
return v !== null && typeof v === "object" && !Array.isArray(v);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createGatewayRouteLogger } from "../lib/route-logger.js";
|
|
2
|
-
import * as os$1 from "node:os";
|
|
3
|
-
import * as path$1 from "node:path";
|
|
4
2
|
import { readdir, realpath, stat } from "node:fs/promises";
|
|
3
|
+
import * as path$1 from "node:path";
|
|
4
|
+
import * as os$1 from "node:os";
|
|
5
5
|
//#region src/gateway/hono/routes/host-fs.ts
|
|
6
6
|
const log = createGatewayRouteLogger("HostFs");
|
|
7
7
|
function jsonError(status, message) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { resolveModelsJsonPath } from "../../../config/paths.js";
|
|
2
|
+
import { CredentialResolver, init_credentials } from "../../../auth/credentials.js";
|
|
2
3
|
import { init_resolve_config_value, testApiKeyResolution } from "../../../config/resolve-config-value.js";
|
|
3
4
|
import { init_models_json, loadModelsJson, saveModelsJson, validateModelsConfig } from "../../../config/models-json.js";
|
|
4
5
|
import { getModelRegistry } from "../../../providers/model-registry.js";
|
|
5
|
-
import { CredentialResolver, init_credentials } from "../../../auth/credentials.js";
|
|
6
6
|
import { getProviderRegistry, init_plugin_registry } from "../../../providers/plugin-registry.js";
|
|
7
7
|
import { PROVIDER_META, getAllModels, getAllProviders, getAvailableModels, getProviderAuthState, init_providers, isProviderConfigured } from "../../../providers/index.js";
|
|
8
8
|
import { getImageGenerationProvider } from "../../../agent/image/generation/provider-registry.js";
|
|
@@ -37,21 +37,10 @@ function parseCaptureSource(body) {
|
|
|
37
37
|
platform: body.platform === "ios" || body.platform === "android" ? body.platform : void 0
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
|
-
function parseBlocks(value) {
|
|
41
|
-
if (!Array.isArray(value)) return void 0;
|
|
42
|
-
return value.filter((block) => {
|
|
43
|
-
if (!block || typeof block !== "object") return false;
|
|
44
|
-
const candidate = block;
|
|
45
|
-
if (typeof candidate.id !== "string" || typeof candidate.type !== "string") return false;
|
|
46
|
-
if (candidate.type === "image") return typeof candidate.attachmentId === "string";
|
|
47
|
-
return true;
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
40
|
function buildNotePatch(body) {
|
|
51
41
|
const patch = {};
|
|
52
42
|
if (typeof body.title === "string") patch.title = body.title;
|
|
53
|
-
if (typeof body.
|
|
54
|
-
if (Array.isArray(body.blocks)) patch.blocks = parseBlocks(body.blocks);
|
|
43
|
+
if (typeof body.markdown === "string") patch.markdown = body.markdown;
|
|
55
44
|
if (typeof body.kind === "string" && VALID_KINDS.has(body.kind)) patch.kind = body.kind;
|
|
56
45
|
if (typeof body.status === "string" && VALID_STATUSES.has(body.status)) patch.status = body.status;
|
|
57
46
|
if (Array.isArray(body.tags)) patch.tags = body.tags.filter((tag) => typeof tag === "string");
|
|
@@ -63,7 +52,7 @@ function buildNotePatch(body) {
|
|
|
63
52
|
}
|
|
64
53
|
function buildNoteThreadContext(note) {
|
|
65
54
|
const title = note.title?.trim() || "未命名笔记";
|
|
66
|
-
const body = note.
|
|
55
|
+
const body = note.markdown.trim() || "这条笔记暂无正文。";
|
|
67
56
|
return [
|
|
68
57
|
`来源 Note:${title}`,
|
|
69
58
|
"",
|
|
@@ -71,7 +60,7 @@ function buildNoteThreadContext(note) {
|
|
|
71
60
|
].join("\n");
|
|
72
61
|
}
|
|
73
62
|
function noteThreadName(note) {
|
|
74
|
-
return `讨论:${note.title?.trim() || note.
|
|
63
|
+
return `讨论:${note.title?.trim() || note.markdown.trim().slice(0, 28) || "未命名笔记"}`;
|
|
75
64
|
}
|
|
76
65
|
function registerNotesRoutes(authenticated, deps) {
|
|
77
66
|
const { service } = deps;
|
|
@@ -114,12 +103,12 @@ function registerNotesRoutes(authenticated, deps) {
|
|
|
114
103
|
} catch {
|
|
115
104
|
return c.json({ error: "Invalid multipart body" }, 400);
|
|
116
105
|
}
|
|
117
|
-
const
|
|
106
|
+
const markdown = typeof body.markdown === "string" ? body.markdown.trim() : void 0;
|
|
118
107
|
const kindRaw = typeof body.kind === "string" ? body.kind : void 0;
|
|
119
108
|
const tagsRaw = typeof body.tags === "string" ? body.tags : void 0;
|
|
120
109
|
const source = parseCaptureSource(body);
|
|
121
110
|
const note = await service.notesServiceInstance.createNote({
|
|
122
|
-
|
|
111
|
+
markdown,
|
|
123
112
|
kind: kindRaw && VALID_KINDS.has(kindRaw) ? kindRaw : void 0,
|
|
124
113
|
tags: tagsRaw ? tagsRaw.split(",").map((t) => t.trim()).filter(Boolean) : void 0,
|
|
125
114
|
capturedVia: source
|
|
@@ -149,14 +138,12 @@ function registerNotesRoutes(authenticated, deps) {
|
|
|
149
138
|
return c.json({ note: full }, 201);
|
|
150
139
|
}
|
|
151
140
|
const body = await c.req.json().catch(() => ({}));
|
|
152
|
-
const
|
|
153
|
-
const blocks = parseBlocks(body.blocks);
|
|
141
|
+
const markdown = typeof body.markdown === "string" ? body.markdown.trim() : void 0;
|
|
154
142
|
const kindRaw = typeof body.kind === "string" ? body.kind : void 0;
|
|
155
143
|
const tagsRaw = Array.isArray(body.tags) ? body.tags.filter((t) => typeof t === "string") : void 0;
|
|
156
144
|
const source = parseCaptureSource(body);
|
|
157
145
|
const note = await service.notesServiceInstance.createNote({
|
|
158
|
-
|
|
159
|
-
blocks,
|
|
146
|
+
markdown,
|
|
160
147
|
kind: kindRaw && VALID_KINDS.has(kindRaw) ? kindRaw : void 0,
|
|
161
148
|
tags: tagsRaw,
|
|
162
149
|
capturedVia: source,
|
|
@@ -315,8 +302,8 @@ function registerNotesRoutes(authenticated, deps) {
|
|
|
315
302
|
const body = await c.req.json().catch(() => ({}));
|
|
316
303
|
const instruction = typeof body.instruction === "string" ? body.instruction.trim() : "";
|
|
317
304
|
if (!instruction) return c.json({ error: "Missing required field: instruction" }, 400);
|
|
318
|
-
const
|
|
319
|
-
const result = await service.notesServiceInstance.createAiEditPatch(id, instruction,
|
|
305
|
+
const markdown = typeof body.markdown === "string" ? body.markdown : void 0;
|
|
306
|
+
const result = await service.notesServiceInstance.createAiEditPatch(id, instruction, markdown);
|
|
320
307
|
if (!result) return c.json({ error: "Note not found" }, 404);
|
|
321
308
|
return c.json(result);
|
|
322
309
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notes.js","names":[],"sources":["../../../../../src/gateway/hono/routes/notes.ts"],"sourcesContent":["import { createReadStream } from 'node:fs';\nimport { access, stat } from 'node:fs/promises';\nimport { Readable } from 'node:stream';\n\nimport type { Hono } from 'hono';\nimport { stream } from 'hono/streaming';\n\nimport { buildSessionKey } from '../../../routing/session-key.js';\nimport { agentExists, getDefaultAgentId } from '../../../routing/resolve-route.js';\nimport type { CaptureChannel, CaptureSource, Note, NoteBlock, NoteKind, NoteStatus, SnapshotTrigger } from '../../../notes/types.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nconst VALID_KINDS = new Set<NoteKind>(['thought', 'todo', 'voice', 'media', 'bookmark', 'mixed', 'task']);\nconst VALID_STATUSES = new Set<NoteStatus>(['inbox', 'processed', 'archived', 'trashed']);\nconst VALID_CHANNELS = new Set<CaptureChannel>(['app', 'web', 'electron', 'tui', 'telegram', 'wechat', 'feishu']);\n\nfunction parseCaptureSource(body: Record<string, unknown>): CaptureSource {\n const channel = typeof body.channel === 'string' && VALID_CHANNELS.has(body.channel as CaptureChannel)\n ? (body.channel as CaptureChannel)\n : 'web';\n const platform = body.platform === 'ios' || body.platform === 'android' ? body.platform : undefined;\n return { channel, platform };\n}\n\nfunction parseBlocks(value: unknown): NoteBlock[] | undefined {\n if (!Array.isArray(value)) return undefined;\n return value.filter((block): block is NoteBlock => {\n if (!block || typeof block !== 'object') return false;\n const candidate = block as Record<string, unknown>;\n if (typeof candidate.id !== 'string' || typeof candidate.type !== 'string') return false;\n if (candidate.type === 'image') {\n return typeof candidate.attachmentId === 'string';\n }\n return true;\n });\n}\n\nfunction buildNotePatch(body: Record<string, unknown>): Partial<Note> {\n const patch: Partial<Note> = {};\n if (typeof body.title === 'string') patch.title = body.title;\n if (typeof body.text === 'string') patch.text = body.text;\n if (Array.isArray(body.blocks)) patch.blocks = parseBlocks(body.blocks);\n if (typeof body.kind === 'string' && VALID_KINDS.has(body.kind as NoteKind)) patch.kind = body.kind as NoteKind;\n if (typeof body.status === 'string' && VALID_STATUSES.has(body.status as NoteStatus)) patch.status = body.status as NoteStatus;\n if (Array.isArray(body.tags)) patch.tags = body.tags.filter((tag): tag is string => typeof tag === 'string');\n if (typeof body.pinned === 'boolean') patch.pinned = body.pinned;\n if (typeof body.localVersion === 'number') patch.localVersion = body.localVersion;\n if (body.ai && typeof body.ai === 'object') patch.ai = body.ai as Note['ai'];\n if (body.aiDeep && typeof body.aiDeep === 'object') patch.aiDeep = body.aiDeep as Note['aiDeep'];\n return patch;\n}\n\nfunction buildNoteThreadContext(note: Note): string {\n const title = note.title?.trim() || '未命名笔记';\n const body = note.text?.trim() || '这条笔记暂无正文。';\n return [`来源 Note:${title}`, '', body].join('\\n');\n}\n\nfunction noteThreadName(note: Note): string {\n const title = note.title?.trim() || note.text?.trim()?.slice(0, 28) || '未命名笔记';\n return `讨论:${title}`;\n}\n\nexport function registerNotesRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n\n // POST /api/notes/quick-capture — minimal text capture\n authenticated.post('/api/notes/quick-capture', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const text = typeof body.text === 'string' ? body.text.trim() : '';\n if (!text) {\n return c.json({ error: 'Missing required field: text' }, 400);\n }\n const source = parseCaptureSource(body);\n const note = await service.notesServiceInstance.quickCapture(text, source);\n return c.json({ note }, 201);\n });\n\n // GET /api/notes — list with filters\n authenticated.get('/api/notes', async (c) => {\n const status = c.req.query('status') as NoteStatus | undefined;\n const kind = c.req.query('kind') as NoteKind | undefined;\n const tag = c.req.query('tag');\n const search = c.req.query('search');\n const pinnedRaw = c.req.query('pinned');\n const limitRaw = c.req.query('limit');\n const offsetRaw = c.req.query('offset');\n const sortBy = c.req.query('sortBy') as 'createdAt' | 'updatedAt' | undefined;\n const sortOrder = c.req.query('sortOrder') as 'asc' | 'desc' | undefined;\n\n const result = await service.notesServiceInstance.listNotes({\n status: status && VALID_STATUSES.has(status) ? status : undefined,\n kind: kind && VALID_KINDS.has(kind) ? kind : undefined,\n tag: tag || undefined,\n search: search || undefined,\n pinned: pinnedRaw === 'true' ? true : pinnedRaw === 'false' ? false : undefined,\n limit: limitRaw ? parseInt(limitRaw, 10) : undefined,\n offset: offsetRaw ? parseInt(offsetRaw, 10) : undefined,\n sortBy: sortBy === 'createdAt' || sortBy === 'updatedAt' ? sortBy : undefined,\n sortOrder: sortOrder === 'asc' || sortOrder === 'desc' ? sortOrder : undefined,\n });\n return c.json(result);\n });\n\n // POST /api/notes — full create (JSON or multipart)\n authenticated.post('/api/notes', async (c) => {\n const contentType = c.req.header('content-type') || '';\n\n if (contentType.includes('multipart/form-data')) {\n let body: Record<string, unknown>;\n try {\n body = await c.req.parseBody({ all: true });\n } catch {\n return c.json({ error: 'Invalid multipart body' }, 400);\n }\n\n const text = typeof body.text === 'string' ? body.text.trim() : undefined;\n const kindRaw = typeof body.kind === 'string' ? body.kind : undefined;\n const tagsRaw = typeof body.tags === 'string' ? body.tags : undefined;\n const source = parseCaptureSource(body as Record<string, unknown>);\n\n const note = await service.notesServiceInstance.createNote({\n text,\n kind: kindRaw && VALID_KINDS.has(kindRaw as NoteKind) ? (kindRaw as NoteKind) : undefined,\n tags: tagsRaw ? tagsRaw.split(',').map((t) => t.trim()).filter(Boolean) : undefined,\n capturedVia: source,\n });\n\n const file = body.file;\n if (file && typeof file === 'object') {\n let buf: Buffer | null = null;\n let fileName = 'upload';\n let mimeType = 'application/octet-stream';\n\n if (file instanceof File) {\n buf = Buffer.from(await file.arrayBuffer());\n fileName = file.name || fileName;\n mimeType = file.type || mimeType;\n } else if (typeof (file as Blob).arrayBuffer === 'function') {\n buf = Buffer.from(await (file as Blob).arrayBuffer());\n }\n\n if (buf) {\n const durationRaw = body.duration;\n const duration =\n typeof durationRaw === 'string'\n ? parseInt(durationRaw, 10)\n : typeof durationRaw === 'number'\n ? durationRaw\n : undefined;\n await service.notesServiceInstance.addAttachment(note.id, {\n name: fileName,\n buffer: buf,\n mimeType,\n duration: Number.isFinite(duration) ? duration : undefined,\n });\n }\n }\n\n const full = await service.notesServiceInstance.getNote(note.id);\n return c.json({ note: full }, 201);\n }\n\n // JSON body\n const body = await c.req.json().catch(() => ({}));\n const text = typeof body.text === 'string' ? body.text.trim() : undefined;\n const blocks = parseBlocks(body.blocks);\n const kindRaw = typeof body.kind === 'string' ? body.kind : undefined;\n const tagsRaw = Array.isArray(body.tags) ? body.tags.filter((t: unknown) => typeof t === 'string') : undefined;\n const source = parseCaptureSource(body);\n\n const note = await service.notesServiceInstance.createNote({\n text,\n blocks,\n kind: kindRaw && VALID_KINDS.has(kindRaw as NoteKind) ? (kindRaw as NoteKind) : undefined,\n tags: tagsRaw,\n capturedVia: source,\n pinned: body.pinned === true,\n });\n return c.json({ note }, 201);\n });\n\n // POST /api/notes/sync — local-first block sync with optimistic conflict check\n authenticated.post('/api/notes/sync', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const noteId = typeof body.noteId === 'string' ? body.noteId : '';\n if (!noteId) {\n return c.json({ error: 'Missing required field: noteId' }, 400);\n }\n\n const baseRemoteVersion = typeof body.baseRemoteVersion === 'number' ? body.baseRemoteVersion : undefined;\n const patch = buildNotePatch(body);\n const result = await service.notesServiceInstance.syncNote(noteId, patch, baseRemoteVersion);\n if (!result.note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n if (result.conflict) {\n return c.json({ conflict: true, note: result.note }, 409);\n }\n return c.json({ conflict: false, note: result.note });\n });\n\n // POST /api/notes/:id/catalyze — generate an AI catalysis report and write it back\n authenticated.post('/api/notes/:id/catalyze', async (c) => {\n const result = await service.notesServiceInstance.catalyzeNote(c.req.param('id'), service.currentConfig);\n if (!result) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json(result);\n });\n\n // POST /api/notes/:id/catalysis-feedback — record whether the catalysis was useful\n authenticated.post('/api/notes/:id/catalysis-feedback', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const feedback = body.feedback;\n if (feedback !== 'helpful' && feedback !== 'not_helpful' && feedback !== 'neutral') {\n return c.json({ error: 'Invalid feedback' }, 400);\n }\n const note = await service.notesServiceInstance.recordCatalysisFeedback(c.req.param('id'), feedback);\n if (!note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ note });\n });\n\n // POST /api/notes/:id/chat — create or reuse a note-bound web chat thread\n authenticated.post('/api/notes/:id/chat', async (c) => {\n const noteId = c.req.param('id');\n const note = await service.notesServiceInstance.getNote(noteId);\n if (!note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n\n const body = await c.req.json().catch(() => ({}));\n const routingCfg = service.currentConfig;\n let agentId =\n typeof body.agentId === 'string' && body.agentId.trim()\n ? body.agentId.trim().toLowerCase()\n : getDefaultAgentId(routingCfg);\n if (!agentExists(agentId, routingCfg)) {\n agentId = getDefaultAgentId(routingCfg);\n }\n\n const existingKey = note.aiDeep?.catalysis?.sourceSessionKey;\n if (existingKey) {\n const existingSession = await service.sessions.getSession(existingKey);\n if (existingSession) {\n return c.json({ session: existingSession, sessionKey: existingKey, reused: true });\n }\n }\n\n const sessionKey = buildSessionKey({\n agentId,\n source: 'webchat',\n accountId: 'default',\n peerKind: 'direct',\n peerId: `note_${noteId}_${Date.now()}`,\n });\n\n await service.sessionIndexInstance.saveMessages(sessionKey, []);\n await service.sessionIndexInstance.appendTranscriptContextEntry(sessionKey, {\n id: `source-note:${noteId}`,\n text: buildNoteThreadContext(note),\n data: {\n kind: 'source_note',\n noteId,\n title: note.title ?? '',\n },\n });\n\n const meta = await service.sessionIndexInstance.getSessionMetadata(sessionKey);\n await service.sessionIndexInstance.updateSessionMetadata(sessionKey, {\n name: noteThreadName(note),\n tags: Array.from(new Set([...(meta?.tags ?? []), 'note'])),\n customData: {\n ...(meta?.customData ?? {}),\n sourceNoteId: noteId,\n sourceNoteTitle: note.title ?? '',\n },\n });\n\n await service.notesServiceInstance.linkNoteThread(noteId, sessionKey);\n const session = await service.sessions.getSession(sessionKey);\n return c.json({ session, sessionKey, reused: false }, 201);\n });\n\n // GET /api/notes/:id/threads — list chat threads linked to a note\n authenticated.get('/api/notes/:id/threads', async (c) => {\n const noteId = c.req.param('id');\n const keys = await service.notesServiceInstance.listNoteThreads(noteId);\n if (!keys) {\n return c.json({ error: 'Note not found' }, 404);\n }\n const sessions = [];\n for (const key of keys) {\n const session = await service.sessions.getSession(key);\n if (session) sessions.push(session);\n }\n return c.json({ items: sessions, total: sessions.length });\n });\n\n // POST /api/notes/:id/append — append assistant output or selected text back to the note\n authenticated.post('/api/notes/:id/append', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const content = typeof body.content === 'string' ? body.content.trim() : '';\n const heading = typeof body.heading === 'string' && body.heading.trim() ? body.heading.trim() : undefined;\n if (!content) {\n return c.json({ error: 'Missing required field: content' }, 400);\n }\n const note = await service.notesServiceInstance.appendTextToNote(c.req.param('id'), content, heading);\n if (!note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ note });\n });\n\n // GET /api/notes/:id — single note\n authenticated.get('/api/notes/:id', async (c) => {\n const id = c.req.param('id');\n const note = await service.notesServiceInstance.getNote(id);\n if (!note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ note });\n });\n\n // PATCH /api/notes/:id — update\n authenticated.patch('/api/notes/:id', async (c) => {\n const id = c.req.param('id');\n const body = await c.req.json().catch(() => ({}));\n\n const patch = buildNotePatch(body);\n const trigger: SnapshotTrigger =\n body.trigger === 'ai_edit' || body.trigger === 'sync' || body.trigger === 'restore'\n ? body.trigger\n : 'edit';\n\n const updated = await service.notesServiceInstance.updateNote(id, patch, trigger);\n if (!updated) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ note: updated });\n });\n\n // DELETE /api/notes/:id — delete note\n authenticated.delete('/api/notes/:id', async (c) => {\n const id = c.req.param('id');\n const removed = await service.notesServiceInstance.deleteNote(id);\n if (!removed) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ deleted: true });\n });\n\n // GET /api/notes/:id/history — list version snapshots\n authenticated.get('/api/notes/:id/history', async (c) => {\n const id = c.req.param('id');\n const entries = await service.notesServiceInstance.listNoteHistory(id);\n return c.json({ entries });\n });\n\n // GET /api/notes/:id/history/:timestamp — get full snapshot\n authenticated.get('/api/notes/:id/history/:timestamp', async (c) => {\n const id = c.req.param('id');\n const timestamp = parseInt(c.req.param('timestamp'), 10);\n if (!Number.isFinite(timestamp)) {\n return c.json({ error: 'Invalid timestamp' }, 400);\n }\n const snapshot = await service.notesServiceInstance.getNoteSnapshot(id, timestamp);\n if (!snapshot) {\n return c.json({ error: 'Snapshot not found' }, 404);\n }\n return c.json({ snapshot });\n });\n\n // POST /api/notes/:id/history/restore — restore a snapshot\n authenticated.post('/api/notes/:id/history/restore', async (c) => {\n const id = c.req.param('id');\n const body = await c.req.json().catch(() => ({}));\n const timestamp = typeof body.timestamp === 'number' ? body.timestamp : 0;\n if (!timestamp) {\n return c.json({ error: 'Missing required field: timestamp' }, 400);\n }\n const note = await service.notesServiceInstance.restoreNoteSnapshot(id, timestamp);\n if (!note) {\n return c.json({ error: 'Snapshot or note not found' }, 404);\n }\n return c.json({ note });\n });\n\n // POST /api/notes/:id/ai/edit — generate previewable block-level AI patch\n authenticated.post('/api/notes/:id/ai/edit', async (c) => {\n const id = c.req.param('id');\n const body = await c.req.json().catch(() => ({}));\n const instruction = typeof body.instruction === 'string' ? body.instruction.trim() : '';\n if (!instruction) {\n return c.json({ error: 'Missing required field: instruction' }, 400);\n }\n\n const blocks = parseBlocks(body.blocks);\n const result = await service.notesServiceInstance.createAiEditPatch(id, instruction, blocks);\n if (!result) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json(result);\n });\n\n // POST /api/notes/:id/media — upload attachment to existing note\n authenticated.post('/api/notes/:id/media', async (c) => {\n const noteId = c.req.param('id');\n let body: Record<string, unknown>;\n try {\n body = await c.req.parseBody({ all: true });\n } catch {\n return c.json({ error: 'Invalid multipart body' }, 400);\n }\n\n const file = body.file;\n if (!file || typeof file !== 'object') {\n return c.json({ error: 'Missing file field' }, 400);\n }\n\n let buf: Buffer;\n let fileName = 'upload';\n let mimeType = 'application/octet-stream';\n\n if (file instanceof File) {\n buf = Buffer.from(await file.arrayBuffer());\n fileName = file.name || fileName;\n mimeType = file.type || mimeType;\n } else if (typeof (file as Blob).arrayBuffer === 'function') {\n buf = Buffer.from(await (file as Blob).arrayBuffer());\n } else {\n return c.json({ error: 'Invalid file upload' }, 400);\n }\n\n const durationRaw = body.duration;\n const duration = typeof durationRaw === 'string' ? parseInt(durationRaw, 10) : undefined;\n\n const attachment = await service.notesServiceInstance.addAttachment(noteId, {\n name: fileName,\n buffer: buf,\n mimeType,\n duration: Number.isFinite(duration) ? duration : undefined,\n });\n\n if (!attachment) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ attachment }, 201);\n });\n\n // GET /api/notes/:id/media/:attachmentId — serve attachment file\n authenticated.get('/api/notes/:id/media/:attachmentId', async (c) => {\n const noteId = c.req.param('id');\n const attachmentId = c.req.param('attachmentId');\n\n const result = await service.notesServiceInstance.getAttachmentPath(noteId, attachmentId);\n if (!result) {\n return c.json({ error: 'Attachment not found' }, 404);\n }\n\n const { filePath, mimeType, fileName } = result;\n\n try {\n await access(filePath);\n } catch {\n return c.json({ error: 'Attachment file missing' }, 404);\n }\n\n const fileStat = await stat(filePath);\n\n c.header('Content-Type', mimeType);\n c.header('Content-Length', String(fileStat.size));\n c.header('Content-Disposition', `inline; filename=\"${encodeURIComponent(fileName)}\"`);\n c.header('Cache-Control', 'private, max-age=31536000, immutable');\n\n return stream(c, async (s) => {\n const readable = Readable.toWeb(createReadStream(filePath)) as ReadableStream<Uint8Array>;\n await s.pipe(readable);\n });\n });\n\n // ── Task / Space / Open tracking ────────────────────────────────────\n\n authenticated.post('/api/notes/task', async (c) => {\n const body = await c.req.json().catch(() => ({})) as Record<string, unknown>;\n const title = typeof body.title === 'string' ? body.title.trim() : '';\n if (!title) return c.json({ error: 'Missing required field: title' }, 400);\n\n const source = parseCaptureSource(body);\n const note = await service.notesServiceInstance.createTask(title, source, {\n dueAt: typeof body.dueAt === 'number' ? body.dueAt : undefined,\n priority: body.priority === 'high' || body.priority === 'medium' || body.priority === 'low' ? body.priority : undefined,\n sourceSessionKey: typeof body.sourceSessionKey === 'string' ? body.sourceSessionKey : undefined,\n sourceNoteId: typeof body.sourceNoteId === 'string' ? body.sourceNoteId : undefined,\n groupId: typeof body.groupId === 'string' ? body.groupId : undefined,\n });\n return c.json({ note }, 201);\n });\n\n authenticated.post('/api/notes/:id/toggle-done', async (c) => {\n const note = await service.notesServiceInstance.toggleTaskDone(c.req.param('id'));\n if (!note) return c.json({ error: 'Not found or not a task' }, 404);\n return c.json({ note });\n });\n\n authenticated.post('/api/notes/:id/open', async (c) => {\n const note = await service.notesServiceInstance.recordOpen(c.req.param('id'));\n if (!note) return c.json({ error: 'Not found' }, 404);\n return c.json({ note });\n });\n\n authenticated.post('/api/notes/:id/move', async (c) => {\n const body = await c.req.json().catch(() => ({})) as Record<string, unknown>;\n const groupId = typeof body.groupId === 'string' ? body.groupId : null;\n const note = await service.notesServiceInstance.moveToGroup(c.req.param('id'), groupId);\n if (!note) return c.json({ error: 'Not found' }, 404);\n return c.json({ note });\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"notes.js","names":[],"sources":["../../../../../src/gateway/hono/routes/notes.ts"],"sourcesContent":["import { createReadStream } from 'node:fs';\nimport { access, stat } from 'node:fs/promises';\nimport { Readable } from 'node:stream';\n\nimport type { Hono } from 'hono';\nimport { stream } from 'hono/streaming';\n\nimport { buildSessionKey } from '../../../routing/session-key.js';\nimport { agentExists, getDefaultAgentId } from '../../../routing/resolve-route.js';\nimport type { CaptureChannel, CaptureSource, Note, NoteKind, NoteStatus, SnapshotTrigger } from '../../../notes/types.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nconst VALID_KINDS = new Set<NoteKind>(['thought', 'todo', 'voice', 'media', 'bookmark', 'mixed', 'task']);\nconst VALID_STATUSES = new Set<NoteStatus>(['inbox', 'processed', 'archived', 'trashed']);\nconst VALID_CHANNELS = new Set<CaptureChannel>(['app', 'web', 'electron', 'tui', 'telegram', 'wechat', 'feishu']);\n\nfunction parseCaptureSource(body: Record<string, unknown>): CaptureSource {\n const channel = typeof body.channel === 'string' && VALID_CHANNELS.has(body.channel as CaptureChannel)\n ? (body.channel as CaptureChannel)\n : 'web';\n const platform = body.platform === 'ios' || body.platform === 'android' ? body.platform : undefined;\n return { channel, platform };\n}\n\nfunction buildNotePatch(body: Record<string, unknown>): Partial<Note> {\n const patch: Partial<Note> = {};\n if (typeof body.title === 'string') patch.title = body.title;\n if (typeof body.markdown === 'string') patch.markdown = body.markdown;\n if (typeof body.kind === 'string' && VALID_KINDS.has(body.kind as NoteKind)) patch.kind = body.kind as NoteKind;\n if (typeof body.status === 'string' && VALID_STATUSES.has(body.status as NoteStatus)) patch.status = body.status as NoteStatus;\n if (Array.isArray(body.tags)) patch.tags = body.tags.filter((tag): tag is string => typeof tag === 'string');\n if (typeof body.pinned === 'boolean') patch.pinned = body.pinned;\n if (typeof body.localVersion === 'number') patch.localVersion = body.localVersion;\n if (body.ai && typeof body.ai === 'object') patch.ai = body.ai as Note['ai'];\n if (body.aiDeep && typeof body.aiDeep === 'object') patch.aiDeep = body.aiDeep as Note['aiDeep'];\n return patch;\n}\n\nfunction buildNoteThreadContext(note: Note): string {\n const title = note.title?.trim() || '未命名笔记';\n const body = note.markdown.trim() || '这条笔记暂无正文。';\n return [`来源 Note:${title}`, '', body].join('\\n');\n}\n\nfunction noteThreadName(note: Note): string {\n const title = note.title?.trim() || note.markdown.trim().slice(0, 28) || '未命名笔记';\n return `讨论:${title}`;\n}\n\nexport function registerNotesRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service } = deps;\n\n // POST /api/notes/quick-capture — minimal text capture\n authenticated.post('/api/notes/quick-capture', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const text = typeof body.text === 'string' ? body.text.trim() : '';\n if (!text) {\n return c.json({ error: 'Missing required field: text' }, 400);\n }\n const source = parseCaptureSource(body);\n const note = await service.notesServiceInstance.quickCapture(text, source);\n return c.json({ note }, 201);\n });\n\n // GET /api/notes — list with filters\n authenticated.get('/api/notes', async (c) => {\n const status = c.req.query('status') as NoteStatus | undefined;\n const kind = c.req.query('kind') as NoteKind | undefined;\n const tag = c.req.query('tag');\n const search = c.req.query('search');\n const pinnedRaw = c.req.query('pinned');\n const limitRaw = c.req.query('limit');\n const offsetRaw = c.req.query('offset');\n const sortBy = c.req.query('sortBy') as 'createdAt' | 'updatedAt' | undefined;\n const sortOrder = c.req.query('sortOrder') as 'asc' | 'desc' | undefined;\n\n const result = await service.notesServiceInstance.listNotes({\n status: status && VALID_STATUSES.has(status) ? status : undefined,\n kind: kind && VALID_KINDS.has(kind) ? kind : undefined,\n tag: tag || undefined,\n search: search || undefined,\n pinned: pinnedRaw === 'true' ? true : pinnedRaw === 'false' ? false : undefined,\n limit: limitRaw ? parseInt(limitRaw, 10) : undefined,\n offset: offsetRaw ? parseInt(offsetRaw, 10) : undefined,\n sortBy: sortBy === 'createdAt' || sortBy === 'updatedAt' ? sortBy : undefined,\n sortOrder: sortOrder === 'asc' || sortOrder === 'desc' ? sortOrder : undefined,\n });\n return c.json(result);\n });\n\n // POST /api/notes — full create (JSON or multipart)\n authenticated.post('/api/notes', async (c) => {\n const contentType = c.req.header('content-type') || '';\n\n if (contentType.includes('multipart/form-data')) {\n let body: Record<string, unknown>;\n try {\n body = await c.req.parseBody({ all: true });\n } catch {\n return c.json({ error: 'Invalid multipart body' }, 400);\n }\n\n const markdown = typeof body.markdown === 'string' ? body.markdown.trim() : undefined;\n const kindRaw = typeof body.kind === 'string' ? body.kind : undefined;\n const tagsRaw = typeof body.tags === 'string' ? body.tags : undefined;\n const source = parseCaptureSource(body as Record<string, unknown>);\n\n const note = await service.notesServiceInstance.createNote({\n markdown,\n kind: kindRaw && VALID_KINDS.has(kindRaw as NoteKind) ? (kindRaw as NoteKind) : undefined,\n tags: tagsRaw ? tagsRaw.split(',').map((t) => t.trim()).filter(Boolean) : undefined,\n capturedVia: source,\n });\n\n const file = body.file;\n if (file && typeof file === 'object') {\n let buf: Buffer | null = null;\n let fileName = 'upload';\n let mimeType = 'application/octet-stream';\n\n if (file instanceof File) {\n buf = Buffer.from(await file.arrayBuffer());\n fileName = file.name || fileName;\n mimeType = file.type || mimeType;\n } else if (typeof (file as Blob).arrayBuffer === 'function') {\n buf = Buffer.from(await (file as Blob).arrayBuffer());\n }\n\n if (buf) {\n const durationRaw = body.duration;\n const duration =\n typeof durationRaw === 'string'\n ? parseInt(durationRaw, 10)\n : typeof durationRaw === 'number'\n ? durationRaw\n : undefined;\n await service.notesServiceInstance.addAttachment(note.id, {\n name: fileName,\n buffer: buf,\n mimeType,\n duration: Number.isFinite(duration) ? duration : undefined,\n });\n }\n }\n\n const full = await service.notesServiceInstance.getNote(note.id);\n return c.json({ note: full }, 201);\n }\n\n // JSON body\n const body = await c.req.json().catch(() => ({}));\n const markdown = typeof body.markdown === 'string' ? body.markdown.trim() : undefined;\n const kindRaw = typeof body.kind === 'string' ? body.kind : undefined;\n const tagsRaw = Array.isArray(body.tags) ? body.tags.filter((t: unknown) => typeof t === 'string') : undefined;\n const source = parseCaptureSource(body);\n\n const note = await service.notesServiceInstance.createNote({\n markdown,\n kind: kindRaw && VALID_KINDS.has(kindRaw as NoteKind) ? (kindRaw as NoteKind) : undefined,\n tags: tagsRaw,\n capturedVia: source,\n pinned: body.pinned === true,\n });\n return c.json({ note }, 201);\n });\n\n // POST /api/notes/sync — local-first markdown sync with optimistic conflict check\n authenticated.post('/api/notes/sync', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const noteId = typeof body.noteId === 'string' ? body.noteId : '';\n if (!noteId) {\n return c.json({ error: 'Missing required field: noteId' }, 400);\n }\n\n const baseRemoteVersion = typeof body.baseRemoteVersion === 'number' ? body.baseRemoteVersion : undefined;\n const patch = buildNotePatch(body);\n const result = await service.notesServiceInstance.syncNote(noteId, patch, baseRemoteVersion);\n if (!result.note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n if (result.conflict) {\n return c.json({ conflict: true, note: result.note }, 409);\n }\n return c.json({ conflict: false, note: result.note });\n });\n\n // POST /api/notes/:id/catalyze — generate an AI catalysis report and write it back\n authenticated.post('/api/notes/:id/catalyze', async (c) => {\n const result = await service.notesServiceInstance.catalyzeNote(c.req.param('id'), service.currentConfig);\n if (!result) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json(result);\n });\n\n // POST /api/notes/:id/catalysis-feedback — record whether the catalysis was useful\n authenticated.post('/api/notes/:id/catalysis-feedback', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const feedback = body.feedback;\n if (feedback !== 'helpful' && feedback !== 'not_helpful' && feedback !== 'neutral') {\n return c.json({ error: 'Invalid feedback' }, 400);\n }\n const note = await service.notesServiceInstance.recordCatalysisFeedback(c.req.param('id'), feedback);\n if (!note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ note });\n });\n\n // POST /api/notes/:id/chat — create or reuse a note-bound web chat thread\n authenticated.post('/api/notes/:id/chat', async (c) => {\n const noteId = c.req.param('id');\n const note = await service.notesServiceInstance.getNote(noteId);\n if (!note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n\n const body = await c.req.json().catch(() => ({}));\n const routingCfg = service.currentConfig;\n let agentId =\n typeof body.agentId === 'string' && body.agentId.trim()\n ? body.agentId.trim().toLowerCase()\n : getDefaultAgentId(routingCfg);\n if (!agentExists(agentId, routingCfg)) {\n agentId = getDefaultAgentId(routingCfg);\n }\n\n const existingKey = note.aiDeep?.catalysis?.sourceSessionKey;\n if (existingKey) {\n const existingSession = await service.sessions.getSession(existingKey);\n if (existingSession) {\n return c.json({ session: existingSession, sessionKey: existingKey, reused: true });\n }\n }\n\n const sessionKey = buildSessionKey({\n agentId,\n source: 'webchat',\n accountId: 'default',\n peerKind: 'direct',\n peerId: `note_${noteId}_${Date.now()}`,\n });\n\n await service.sessionIndexInstance.saveMessages(sessionKey, []);\n await service.sessionIndexInstance.appendTranscriptContextEntry(sessionKey, {\n id: `source-note:${noteId}`,\n text: buildNoteThreadContext(note),\n data: {\n kind: 'source_note',\n noteId,\n title: note.title ?? '',\n },\n });\n\n const meta = await service.sessionIndexInstance.getSessionMetadata(sessionKey);\n await service.sessionIndexInstance.updateSessionMetadata(sessionKey, {\n name: noteThreadName(note),\n tags: Array.from(new Set([...(meta?.tags ?? []), 'note'])),\n customData: {\n ...(meta?.customData ?? {}),\n sourceNoteId: noteId,\n sourceNoteTitle: note.title ?? '',\n },\n });\n\n await service.notesServiceInstance.linkNoteThread(noteId, sessionKey);\n const session = await service.sessions.getSession(sessionKey);\n return c.json({ session, sessionKey, reused: false }, 201);\n });\n\n // GET /api/notes/:id/threads — list chat threads linked to a note\n authenticated.get('/api/notes/:id/threads', async (c) => {\n const noteId = c.req.param('id');\n const keys = await service.notesServiceInstance.listNoteThreads(noteId);\n if (!keys) {\n return c.json({ error: 'Note not found' }, 404);\n }\n const sessions = [];\n for (const key of keys) {\n const session = await service.sessions.getSession(key);\n if (session) sessions.push(session);\n }\n return c.json({ items: sessions, total: sessions.length });\n });\n\n // POST /api/notes/:id/append — append assistant output or selected text back to the note\n authenticated.post('/api/notes/:id/append', async (c) => {\n const body = await c.req.json().catch(() => ({}));\n const content = typeof body.content === 'string' ? body.content.trim() : '';\n const heading = typeof body.heading === 'string' && body.heading.trim() ? body.heading.trim() : undefined;\n if (!content) {\n return c.json({ error: 'Missing required field: content' }, 400);\n }\n const note = await service.notesServiceInstance.appendTextToNote(c.req.param('id'), content, heading);\n if (!note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ note });\n });\n\n // GET /api/notes/:id — single note\n authenticated.get('/api/notes/:id', async (c) => {\n const id = c.req.param('id');\n const note = await service.notesServiceInstance.getNote(id);\n if (!note) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ note });\n });\n\n // PATCH /api/notes/:id — update\n authenticated.patch('/api/notes/:id', async (c) => {\n const id = c.req.param('id');\n const body = await c.req.json().catch(() => ({}));\n\n const patch = buildNotePatch(body);\n const trigger: SnapshotTrigger =\n body.trigger === 'ai_edit' || body.trigger === 'sync' || body.trigger === 'restore'\n ? body.trigger\n : 'edit';\n\n const updated = await service.notesServiceInstance.updateNote(id, patch, trigger);\n if (!updated) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ note: updated });\n });\n\n // DELETE /api/notes/:id — delete note\n authenticated.delete('/api/notes/:id', async (c) => {\n const id = c.req.param('id');\n const removed = await service.notesServiceInstance.deleteNote(id);\n if (!removed) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ deleted: true });\n });\n\n // GET /api/notes/:id/history — list version snapshots\n authenticated.get('/api/notes/:id/history', async (c) => {\n const id = c.req.param('id');\n const entries = await service.notesServiceInstance.listNoteHistory(id);\n return c.json({ entries });\n });\n\n // GET /api/notes/:id/history/:timestamp — get full snapshot\n authenticated.get('/api/notes/:id/history/:timestamp', async (c) => {\n const id = c.req.param('id');\n const timestamp = parseInt(c.req.param('timestamp'), 10);\n if (!Number.isFinite(timestamp)) {\n return c.json({ error: 'Invalid timestamp' }, 400);\n }\n const snapshot = await service.notesServiceInstance.getNoteSnapshot(id, timestamp);\n if (!snapshot) {\n return c.json({ error: 'Snapshot not found' }, 404);\n }\n return c.json({ snapshot });\n });\n\n // POST /api/notes/:id/history/restore — restore a snapshot\n authenticated.post('/api/notes/:id/history/restore', async (c) => {\n const id = c.req.param('id');\n const body = await c.req.json().catch(() => ({}));\n const timestamp = typeof body.timestamp === 'number' ? body.timestamp : 0;\n if (!timestamp) {\n return c.json({ error: 'Missing required field: timestamp' }, 400);\n }\n const note = await service.notesServiceInstance.restoreNoteSnapshot(id, timestamp);\n if (!note) {\n return c.json({ error: 'Snapshot or note not found' }, 404);\n }\n return c.json({ note });\n });\n\n // POST /api/notes/:id/ai/edit — generate previewable markdown AI patch\n authenticated.post('/api/notes/:id/ai/edit', async (c) => {\n const id = c.req.param('id');\n const body = await c.req.json().catch(() => ({}));\n const instruction = typeof body.instruction === 'string' ? body.instruction.trim() : '';\n if (!instruction) {\n return c.json({ error: 'Missing required field: instruction' }, 400);\n }\n\n const markdown = typeof body.markdown === 'string' ? body.markdown : undefined;\n const result = await service.notesServiceInstance.createAiEditPatch(id, instruction, markdown);\n if (!result) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json(result);\n });\n\n // POST /api/notes/:id/media — upload attachment to existing note\n authenticated.post('/api/notes/:id/media', async (c) => {\n const noteId = c.req.param('id');\n let body: Record<string, unknown>;\n try {\n body = await c.req.parseBody({ all: true });\n } catch {\n return c.json({ error: 'Invalid multipart body' }, 400);\n }\n\n const file = body.file;\n if (!file || typeof file !== 'object') {\n return c.json({ error: 'Missing file field' }, 400);\n }\n\n let buf: Buffer;\n let fileName = 'upload';\n let mimeType = 'application/octet-stream';\n\n if (file instanceof File) {\n buf = Buffer.from(await file.arrayBuffer());\n fileName = file.name || fileName;\n mimeType = file.type || mimeType;\n } else if (typeof (file as Blob).arrayBuffer === 'function') {\n buf = Buffer.from(await (file as Blob).arrayBuffer());\n } else {\n return c.json({ error: 'Invalid file upload' }, 400);\n }\n\n const durationRaw = body.duration;\n const duration = typeof durationRaw === 'string' ? parseInt(durationRaw, 10) : undefined;\n\n const attachment = await service.notesServiceInstance.addAttachment(noteId, {\n name: fileName,\n buffer: buf,\n mimeType,\n duration: Number.isFinite(duration) ? duration : undefined,\n });\n\n if (!attachment) {\n return c.json({ error: 'Note not found' }, 404);\n }\n return c.json({ attachment }, 201);\n });\n\n // GET /api/notes/:id/media/:attachmentId — serve attachment file\n authenticated.get('/api/notes/:id/media/:attachmentId', async (c) => {\n const noteId = c.req.param('id');\n const attachmentId = c.req.param('attachmentId');\n\n const result = await service.notesServiceInstance.getAttachmentPath(noteId, attachmentId);\n if (!result) {\n return c.json({ error: 'Attachment not found' }, 404);\n }\n\n const { filePath, mimeType, fileName } = result;\n\n try {\n await access(filePath);\n } catch {\n return c.json({ error: 'Attachment file missing' }, 404);\n }\n\n const fileStat = await stat(filePath);\n\n c.header('Content-Type', mimeType);\n c.header('Content-Length', String(fileStat.size));\n c.header('Content-Disposition', `inline; filename=\"${encodeURIComponent(fileName)}\"`);\n c.header('Cache-Control', 'private, max-age=31536000, immutable');\n\n return stream(c, async (s) => {\n const readable = Readable.toWeb(createReadStream(filePath)) as ReadableStream<Uint8Array>;\n await s.pipe(readable);\n });\n });\n\n // ── Task / Space / Open tracking ────────────────────────────────────\n\n authenticated.post('/api/notes/task', async (c) => {\n const body = await c.req.json().catch(() => ({})) as Record<string, unknown>;\n const title = typeof body.title === 'string' ? body.title.trim() : '';\n if (!title) return c.json({ error: 'Missing required field: title' }, 400);\n\n const source = parseCaptureSource(body);\n const note = await service.notesServiceInstance.createTask(title, source, {\n dueAt: typeof body.dueAt === 'number' ? body.dueAt : undefined,\n priority: body.priority === 'high' || body.priority === 'medium' || body.priority === 'low' ? body.priority : undefined,\n sourceSessionKey: typeof body.sourceSessionKey === 'string' ? body.sourceSessionKey : undefined,\n sourceNoteId: typeof body.sourceNoteId === 'string' ? body.sourceNoteId : undefined,\n groupId: typeof body.groupId === 'string' ? body.groupId : undefined,\n });\n return c.json({ note }, 201);\n });\n\n authenticated.post('/api/notes/:id/toggle-done', async (c) => {\n const note = await service.notesServiceInstance.toggleTaskDone(c.req.param('id'));\n if (!note) return c.json({ error: 'Not found or not a task' }, 404);\n return c.json({ note });\n });\n\n authenticated.post('/api/notes/:id/open', async (c) => {\n const note = await service.notesServiceInstance.recordOpen(c.req.param('id'));\n if (!note) return c.json({ error: 'Not found' }, 404);\n return c.json({ note });\n });\n\n authenticated.post('/api/notes/:id/move', async (c) => {\n const body = await c.req.json().catch(() => ({})) as Record<string, unknown>;\n const groupId = typeof body.groupId === 'string' ? body.groupId : null;\n const note = await service.notesServiceInstance.moveToGroup(c.req.param('id'), groupId);\n if (!note) return c.json({ error: 'Not found' }, 404);\n return c.json({ note });\n });\n}\n"],"mappings":"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"}
|
|
@@ -13,8 +13,8 @@ import { getClientIpFromHeaders } from "../../security/loopback.js";
|
|
|
13
13
|
import { renderFolderLandingPage, renderShareExpiredPage, renderShareLandingPage } from "../../../share/share-landing.js";
|
|
14
14
|
import { consumeSharePublicLimit } from "../../../share/share-rate-limit.js";
|
|
15
15
|
import { createZipStream, planDirectoryFiles } from "../../../share/share-zip.js";
|
|
16
|
-
import { createReadStream } from "node:fs";
|
|
17
16
|
import { createHash } from "node:crypto";
|
|
17
|
+
import { createReadStream } from "node:fs";
|
|
18
18
|
import { stat } from "node:fs/promises";
|
|
19
19
|
import { Readable } from "node:stream";
|
|
20
20
|
//#region src/gateway/hono/routes/shares.ts
|
|
@@ -8,10 +8,10 @@ import { resolveHeartbeatMdPath } from "../../workspace-heartbeat-path.js";
|
|
|
8
8
|
import { createGatewayRouteLogger } from "../lib/route-logger.js";
|
|
9
9
|
import { listWorkspaceRelativeFilesFsFallback } from "../../workspace-fs-file-list.js";
|
|
10
10
|
import { runRipgrepInDirectory, runRipgrepListFiles } from "../../workspace-ripgrep.js";
|
|
11
|
-
import { basename, dirname, join, resolve } from "node:path";
|
|
12
|
-
import { constants } from "node:fs";
|
|
13
11
|
import { randomUUID } from "node:crypto";
|
|
12
|
+
import { constants } from "node:fs";
|
|
14
13
|
import { copyFile, link, mkdir, readFile, readdir, rename, stat, unlink, writeFile } from "node:fs/promises";
|
|
14
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
15
15
|
//#region src/gateway/hono/routes/workspace.ts
|
|
16
16
|
init_agent_scope();
|
|
17
17
|
const log = createGatewayRouteLogger("Workspace");
|
package/dist/src/gateway/lock.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import path from "node:path";
|
|
2
|
-
import net from "node:net";
|
|
3
|
-
import fs from "node:fs";
|
|
4
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
5
3
|
import fs$1 from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import net from "node:net";
|
|
6
6
|
import { homedir } from "os";
|
|
7
7
|
//#region src/gateway/lock.ts
|
|
8
8
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createLogger } from "../utils/logger/index.js";
|
|
2
2
|
import { init_logger } from "../utils/logger.js";
|
|
3
|
-
import net from "node:net";
|
|
4
3
|
import fs from "node:fs";
|
|
4
|
+
import net from "node:net";
|
|
5
5
|
import { execFileSync } from "node:child_process";
|
|
6
6
|
//#region src/gateway/ports.ts
|
|
7
7
|
/**
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { buildSessionKey, init_session_key, parseSessionKey } from "../../routing/session-key.js";
|
|
2
|
-
import { getDefaultAgentId, init_resolve_route } from "../../routing/resolve-route.js";
|
|
3
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
4
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { buildSessionKey, init_session_key, parseSessionKey } from "../../routing/session-key.js";
|
|
4
|
+
import { getDefaultAgentId, init_resolve_route } from "../../routing/resolve-route.js";
|
|
5
5
|
import { AgentRunRelay } from "../agent-run-relay.js";
|
|
6
6
|
import { ClarifyBridge } from "../clarify-bridge.js";
|
|
7
7
|
import { runGatewayAgent } from "./run-gateway-agent.js";
|