@ljwei-stak/dsh-model-route-bot 0.66.4 → 0.67.0
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/.dsh-plugin/bot-product.mjs +81 -5
- package/.dsh-plugin/client.js +17490 -1791
- package/README.i18n.yaml +4 -4
- package/README.md +409 -364
- package/README.zh.md +409 -364
- package/apps/integration-client/README.md +31 -7
- package/apps/integration-client/api.mjs +14 -3
- package/apps/integration-client/binding-editor.jsx +308 -109
- package/apps/integration-client/binding-model.mjs +262 -0
- package/apps/integration-client/binding.css +144 -0
- package/apps/integration-client/bot-model-status.mjs +18 -0
- package/apps/integration-client/bot-profile-identity.jsx +197 -0
- package/apps/integration-client/bot-profile.css +57 -0
- package/apps/integration-client/bot-profile.mjs +97 -0
- package/apps/integration-client/bot-settings-dialog.css +18 -0
- package/apps/integration-client/bot-settings-dialog.jsx +111 -0
- package/apps/integration-client/bot-thread-header-bridge.css +20 -0
- package/apps/integration-client/bot-thread-header.jsx +278 -0
- package/apps/integration-client/bot-threads-panel.jsx +378 -0
- package/apps/integration-client/bot-threads.css +169 -0
- package/apps/integration-client/chat-design.mjs +250 -0
- package/apps/integration-client/chat-ui.jsx +175 -0
- package/apps/integration-client/chat.css +477 -0
- package/apps/integration-client/composer-draft-binding.mjs +50 -0
- package/apps/integration-client/composer-draft-bound.jsx +14 -0
- package/apps/integration-client/composer-draft-host.jsx +142 -0
- package/apps/integration-client/composer-draft-session.jsx +287 -0
- package/apps/integration-client/composer-draft-witness.mjs +115 -0
- package/apps/integration-client/composer-draft.css +4 -0
- package/apps/integration-client/composer-draft.mjs +322 -0
- package/apps/integration-client/contact-attention.jsx +54 -0
- package/apps/integration-client/data-panel.jsx +439 -0
- package/apps/integration-client/data.css +69 -0
- package/apps/integration-client/desktop-bridge.mjs +1 -0
- package/apps/integration-client/desktop-http-socket.mjs +49 -0
- package/apps/integration-client/desktop-keyboard.mjs +32 -0
- package/apps/integration-client/desktop-pane.jsx +99 -30
- package/apps/integration-client/desktop-stream.mjs +13 -3
- package/apps/integration-client/desktop-tools.jsx +19 -0
- package/apps/integration-client/desktop-touch.mjs +27 -0
- package/apps/integration-client/desktop.css +41 -0
- package/apps/integration-client/independent-chat-controller.mjs +224 -0
- package/apps/integration-client/independent-chat-entry.jsx +61 -0
- package/apps/integration-client/independent-chat-navigation.mjs +21 -0
- package/apps/integration-client/independent-chat-page.jsx +148 -0
- package/apps/integration-client/independent-chat-rich.jsx +64 -0
- package/apps/integration-client/independent-chat-rich.mjs +30 -0
- package/apps/integration-client/independent-chat.css +73 -0
- package/apps/integration-client/index.jsx +24 -16
- package/apps/integration-client/library-panel.jsx +4 -1
- package/apps/integration-client/licenses/jsqr-1.4.0-LICENSE.txt +202 -0
- package/apps/integration-client/main-route-editor.jsx +94 -0
- package/apps/integration-client/main-route-model.mjs +100 -0
- package/apps/integration-client/model-picker.css +37 -0
- package/apps/integration-client/model-picker.jsx +83 -0
- package/apps/integration-client/native-activity.css +141 -0
- package/apps/integration-client/native-activity.jsx +276 -0
- package/apps/integration-client/native-activity.mjs +384 -0
- package/apps/integration-client/notifications-panel.jsx +186 -0
- package/apps/integration-client/notifications.css +126 -0
- package/apps/integration-client/pairing-qr.jsx +79 -0
- package/apps/integration-client/panels.jsx +126 -115
- package/apps/integration-client/product-slots.jsx +46 -0
- package/apps/integration-client/routine-recorder.mjs +23 -2
- package/apps/integration-client/secure-pairing.jsx +84 -0
- package/apps/integration-client/tasks-panel.jsx +32 -10
- package/apps/integration-client/ui-icons.jsx +17 -0
- package/apps/integration-client/usage-explorer.jsx +43 -0
- package/apps/integration-client/usage-report.mjs +71 -0
- package/apps/integration-client/usage.css +34 -0
- package/apps/integration-client/web-panel-model.mjs +140 -0
- package/apps/integration-client/web-panel-page.jsx +221 -0
- package/apps/integration-client/web-panel-pins-live.jsx +28 -0
- package/apps/integration-client/web-panel.css +139 -0
- package/apps/integration-client/workspace-model.mjs +67 -0
- package/apps/integration-client/workspace-navigation.mjs +56 -0
- package/apps/integration-client/workspace-ui.jsx +173 -0
- package/apps/integration-client/workspace.css +332 -0
- package/modules/bot-runtime/SOURCE.json +176 -50
- package/modules/bot-runtime/index.mjs +169 -13
- package/modules/bot-runtime/product-overlay/OVERLAY.json +128 -2
- package/modules/bot-runtime/product-overlay/base/src/client/header.js +244 -0
- package/modules/bot-runtime/product-overlay/base/src/client/learning-card.js +202 -0
- package/modules/bot-runtime/product-overlay/base/src/client/model-menu.js +371 -0
- package/modules/bot-runtime/product-overlay/base/src/client/secret-card.js +363 -0
- package/modules/bot-runtime/product-overlay/base/src/client/sources.js +68 -0
- package/modules/bot-runtime/product-overlay/base/src/client/turn-error.js +260 -0
- package/modules/bot-runtime/product-overlay/base/src/host/channel.js +647 -0
- package/modules/bot-runtime/product-overlay/base/src/host/memory.js +2050 -0
- package/modules/bot-runtime/product-overlay/base/src/host/models.js +314 -0
- package/modules/bot-runtime/product-overlay/base/src/host/parts.js +1473 -0
- package/modules/bot-runtime/product-overlay/base/src/host/privacy.js +368 -0
- package/modules/bot-runtime/product-overlay/base/src/host/roster.js +776 -0
- package/modules/bot-runtime/product-overlay/base/src/host/store.js +512 -0
- package/modules/bot-runtime/product-overlay/base/src/host/usage.js +653 -0
- package/modules/bot-runtime/product-overlay/patches/src/client/details-drawer.js.patch +48 -2
- package/modules/bot-runtime/product-overlay/patches/src/client/header.js.patch +41 -0
- package/modules/bot-runtime/product-overlay/patches/src/client/index.js.patch +33 -1
- package/modules/bot-runtime/product-overlay/patches/src/client/learning-card.js.patch +20 -0
- package/modules/bot-runtime/product-overlay/patches/src/client/model-menu.js.patch +24 -0
- package/modules/bot-runtime/product-overlay/patches/src/client/secret-card.js.patch +25 -0
- package/modules/bot-runtime/product-overlay/patches/src/client/sources.js.patch +52 -0
- package/modules/bot-runtime/product-overlay/patches/src/client/turn-error.js.patch +23 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/channel.js.patch +46 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/memory.js.patch +11 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/models.js.patch +16 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/parts.js.patch +95 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/privacy.js.patch +11 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/roster.js.patch +145 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/store.js.patch +68 -0
- package/modules/bot-runtime/product-overlay/patches/src/host/usage.js.patch +11 -0
- package/modules/bot-runtime/read-model.mjs +19 -4
- package/modules/bot-runtime/vendor/ds-bot/src/client/details-drawer.js +15 -5
- package/modules/bot-runtime/vendor/ds-bot/src/client/header.js +9 -2
- package/modules/bot-runtime/vendor/ds-bot/src/client/index.js +9 -2
- package/modules/bot-runtime/vendor/ds-bot/src/client/learning-card.js +2 -2
- package/modules/bot-runtime/vendor/ds-bot/src/client/model-menu.js +5 -3
- package/modules/bot-runtime/vendor/ds-bot/src/client/secret-card.js +3 -3
- package/modules/bot-runtime/vendor/ds-bot/src/client/sources.js +25 -2
- package/modules/bot-runtime/vendor/ds-bot/src/client/turn-error.js +3 -2
- package/modules/bot-runtime/vendor/ds-bot/src/host/channel.js +14 -2
- package/modules/bot-runtime/vendor/ds-bot/src/host/memory.js +1 -1
- package/modules/bot-runtime/vendor/ds-bot/src/host/models.js +7 -0
- package/modules/bot-runtime/vendor/ds-bot/src/host/parts.js +26 -9
- package/modules/bot-runtime/vendor/ds-bot/src/host/privacy.js +1 -1
- package/modules/bot-runtime/vendor/ds-bot/src/host/roster.js +112 -3
- package/modules/bot-runtime/vendor/ds-bot/src/host/store.js +34 -1
- package/modules/bot-runtime/vendor/ds-bot/src/host/usage.js +1 -1
- package/modules/independent-runtime/index.mjs +152 -62
- package/modules/independent-runtime/remote-tools.mjs +8 -5
- package/modules/openmaus-protocol/NOTICE +10 -0
- package/modules/openmaus-protocol/README.md +15 -0
- package/modules/openmaus-protocol/SOURCE.json +68 -0
- package/modules/openmaus-protocol/dist/protocol.mjs +1203 -0
- package/modules/openmaus-protocol/index.mjs +1 -0
- package/modules/openmaus-protocol/transport.mjs +77 -0
- package/modules/openmaus-protocol/vendor/LICENSE +202 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/README.md +405 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/credentials.ts +128 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/descriptor.ts +84 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/noise.ts +456 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/phone.ts +104 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/session.ts +417 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/vectors/v1.json +2565 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/vectors/v1.sha256 +1 -0
- package/modules/openmaus-protocol/vendor/companion/src/e2e/yamux.ts +335 -0
- package/package.json +18 -6
- package/packages/bot-acp/README.md +156 -0
- package/packages/bot-acp/licenses/LICENSE-OpenMausBot +202 -0
- package/packages/bot-acp/licenses/NOTICE.md +27 -0
- package/packages/bot-acp/src/acp-adapter.mjs +795 -0
- package/packages/bot-acp/src/acp-host.mjs +148 -0
- package/packages/bot-acp/src/native-launch.mjs +121 -0
- package/packages/bot-acp/src/permission-policy.mjs +283 -0
- package/packages/bot-acp/src/rpc-codec.mjs +265 -0
- package/packages/bot-acp/src/session-core.mjs +581 -0
- package/packages/bot-acp/src/stdio-rpc.mjs +329 -0
- package/packages/bot-engines/README.md +281 -0
- package/packages/bot-engines/licenses/LICENSE-OpenMausBot +202 -0
- package/packages/bot-engines/licenses/NOTICE.md +32 -0
- package/packages/bot-engines/src/claude-engine.mjs +772 -0
- package/packages/bot-engines/src/claude-llm-adapter.mjs +797 -0
- package/packages/bot-engines/src/claude-llm-turn.mjs +292 -0
- package/packages/bot-engines/src/claude-permission-broker.mjs +130 -0
- package/packages/bot-engines/src/claude-permission-proxy.mjs +87 -0
- package/packages/bot-engines/src/claude-protocol.mjs +177 -0
- package/packages/bot-engines/src/driver-catalog.mjs +334 -0
- package/packages/bot-engines/src/host-loop-request.mjs +95 -0
- package/packages/bot-engines/src/host-registrations.mjs +105 -0
- package/packages/capability-broker/src/cli-bootstrap.mjs +86 -16
- package/packages/capability-broker/src/cli-bridge-response.mjs +80 -0
- package/packages/capability-broker/src/cli-stdio-bridge.mjs +21 -8
- package/packages/cli-runtime/src/codex-session-core.mjs +4 -0
- package/packages/cli-runtime/src/native-cli-output.mjs +57 -0
- package/packages/cli-runtime/src/native-peer.ps1 +51 -3
- package/packages/cli-runtime/src/native-process.mjs +77 -14
- package/packages/model-router-plugin/package.json +1 -1
- package/packages/orchestration/src/binding-product.mjs +19 -0
- package/packages/orchestration/src/bot-data-actions.mjs +45 -0
- package/packages/orchestration/src/bot-data-chart.mjs +109 -0
- package/packages/orchestration/src/bot-data-context.mjs +44 -0
- package/packages/orchestration/src/bot-data-engine.mjs +809 -0
- package/packages/orchestration/src/bot-data-io.mjs +186 -0
- package/packages/orchestration/src/bot-data-sql.mjs +195 -0
- package/packages/orchestration/src/bot-data-surface.mjs +144 -0
- package/packages/orchestration/src/bot-data-tools.mjs +68 -0
- package/packages/orchestration/src/bot-data-worker.mjs +228 -0
- package/packages/orchestration/src/bot-independent-execution.mjs +195 -0
- package/packages/orchestration/src/bot-independent-stream.mjs +74 -0
- package/packages/orchestration/src/bot-loop.mjs +152 -19
- package/packages/orchestration/src/bot-notifications.mjs +159 -0
- package/packages/orchestration/src/bot-policy.mjs +43 -4
- package/packages/orchestration/src/bot-profile.mjs +171 -0
- package/packages/orchestration/src/bot-routine.mjs +4 -4
- package/packages/orchestration/src/bot-runtime-assembly.mjs +255 -8
- package/packages/orchestration/src/bot-runtime-switch.mjs +13 -2
- package/packages/orchestration/src/bot-serving.mjs +164 -0
- package/packages/orchestration/src/bot-session-store.mjs +105 -9
- package/packages/orchestration/src/bot-settings.mjs +50 -11
- package/packages/orchestration/src/bot-thread-admission.mjs +84 -0
- package/packages/orchestration/src/bot-thread-host.mjs +187 -0
- package/packages/orchestration/src/bot-threads.mjs +790 -0
- package/packages/orchestration/src/data-product-access.mjs +37 -0
- package/packages/orchestration/src/data-tool-contract.mjs +291 -0
- package/packages/orchestration/src/desktop-http-carrier.mjs +120 -0
- package/packages/orchestration/src/desktop-proxy.mjs +311 -0
- package/packages/orchestration/src/desktop-sessions.mjs +43 -9
- package/packages/orchestration/src/ds-lifecycle.mjs +31 -4
- package/packages/orchestration/src/grant-refresh-queue.mjs +17 -0
- package/packages/orchestration/src/independent-chat-page.mjs +39 -0
- package/packages/orchestration/src/independent-chat-service.mjs +308 -0
- package/packages/orchestration/src/independent-context-state.mjs +44 -0
- package/packages/orchestration/src/independent-message-wire.mjs +84 -0
- package/packages/orchestration/src/independent-tool-catalog.mjs +175 -0
- package/packages/orchestration/src/independent-tool-families.mjs +73 -0
- package/packages/orchestration/src/independent-tool-host.mjs +344 -0
- package/packages/orchestration/src/main-bot-grant.mjs +15 -0
- package/packages/orchestration/src/main-model-routes.mjs +208 -0
- package/packages/orchestration/src/model-accounting.mjs +99 -35
- package/packages/orchestration/src/model-auxiliary-dispatch.mjs +187 -0
- package/packages/orchestration/src/model-loop-frame.mjs +179 -0
- package/packages/orchestration/src/model-prepared-generation.mjs +175 -0
- package/packages/orchestration/src/model-request-bounds.mjs +111 -0
- package/packages/orchestration/src/native-activity-contract.mjs +491 -0
- package/packages/orchestration/src/native-activity-service.mjs +102 -0
- package/packages/orchestration/src/native-activity-store.mjs +249 -0
- package/packages/orchestration/src/native-conversation-tools.mjs +78 -0
- package/packages/orchestration/src/native-data-tools.mjs +100 -0
- package/packages/orchestration/src/native-remote-actions.mjs +742 -0
- package/packages/orchestration/src/native-team-tools.mjs +73 -0
- package/packages/orchestration/src/pairing-invite.mjs +37 -0
- package/packages/orchestration/src/product-composition.mjs +1559 -1001
- package/packages/orchestration/src/remote-machines.mjs +82 -14
- package/packages/orchestration/src/routine-execution.mjs +5 -3
- package/packages/orchestration/src/routine-session.mjs +19 -13
- package/packages/orchestration/src/secure-pairing-host.mjs +112 -0
- package/packages/orchestration/src/task-journal.mjs +29 -0
- package/packages/orchestration/src/task-product.mjs +17 -0
- package/packages/orchestration/src/team-assignment-store.mjs +120 -0
- package/packages/orchestration/src/team-bridge.mjs +282 -0
- package/packages/orchestration/src/team-scheduler.mjs +83 -0
- package/packages/orchestration/src/team-sdk-tools.mjs +84 -0
- package/packages/orchestration/src/team-tool-contract.mjs +284 -0
- package/packages/orchestration/src/ui-host-namespace.mjs +23 -0
- package/packages/orchestration/src/web-panel-actions.mjs +103 -0
- package/packages/orchestration/src/web-panel-framing.mjs +227 -0
- package/packages/orchestration/src/web-panel-store.mjs +206 -0
- package/remote-computer-agent/README.md +39 -29
- package/remote-computer-agent/build.mjs +3 -0
- package/remote-computer-agent/dist/OPENMAUSBOT_LICENSE +202 -0
- package/remote-computer-agent/dist/OPENMAUSBOT_NOTICE +10 -0
- package/remote-computer-agent/dist/OPENMAUSBOT_SOURCE.json +68 -0
- package/remote-computer-agent/dist/cli-stdio-bridge.mjs +215 -25
- package/remote-computer-agent/dist/cli-stdio-bridge.mjs.map +4 -4
- package/remote-computer-agent/dist/cli.mjs +1688 -168
- package/remote-computer-agent/dist/cli.mjs.map +4 -4
- package/remote-computer-agent/dist/index.mjs +1579 -122
- package/remote-computer-agent/dist/index.mjs.map +4 -4
- package/remote-computer-agent/dist/native-peer.ps1 +51 -3
- package/remote-computer-agent/package-lock.json +308 -2
- package/remote-computer-agent/package.json +2 -1
- package/remote-computer-agent/pair-device.ps1 +20 -0
- package/remote-computer-agent/setup.ps1 +38 -16
- package/remote-computer-agent/src/cli.ts +24 -3
- package/remote-computer-agent/src/desktop-session.ts +11 -3
- package/remote-computer-agent/src/e2e-server.ts +81 -0
- package/remote-computer-agent/src/pairing-page.ts +35 -0
- package/remote-computer-agent/src/protocol.ts +25 -25
- package/remote-computer-agent/src/secure-pairing.ts +105 -0
- package/remote-computer-agent/src/store.ts +20 -5
- package/remote-computer-agent/src/transport.ts +39 -15
|
@@ -1,12 +1,69 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process'
|
|
2
2
|
import { EventEmitter } from 'node:events'
|
|
3
3
|
import { StringDecoder } from 'node:string_decoder'
|
|
4
|
-
import { access, realpath } from 'node:fs/promises'
|
|
5
|
-
import {
|
|
4
|
+
import { access, lstat, readFile, readdir, realpath, rmdir, unlink } from 'node:fs/promises'
|
|
5
|
+
import { lstatSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, writeFileSync } from 'node:fs'
|
|
6
|
+
import { randomBytes } from 'node:crypto'
|
|
7
|
+
import { tmpdir } from 'node:os'
|
|
8
|
+
import { basename, dirname, isAbsolute, join } from 'node:path'
|
|
6
9
|
import { fileURLToPath } from 'node:url'
|
|
10
|
+
import { NativeCliOutput } from './native-cli-output.mjs'
|
|
7
11
|
|
|
8
12
|
const HERE = fileURLToPath(new URL('.', import.meta.url))
|
|
9
13
|
const MAX_FRAME = 262_144
|
|
14
|
+
const COMPILER_ROOT = 'DSH_NATIVE_COMPILER_ROOT'
|
|
15
|
+
const COMPILER_SCRATCH = 'DSH_NATIVE_COMPILER_SCRATCH'
|
|
16
|
+
// Capture only the trusted Host launch environment, never a model's spec or an
|
|
17
|
+
// env argument. A packaged bridge inherits this one non-secret root hint so its
|
|
18
|
+
// compiler does not start a new root beneath an ever-deeper private TEMP.
|
|
19
|
+
const inheritedCompilerRoot = process.platform === 'win32' ? process.env[COMPILER_ROOT] : undefined
|
|
20
|
+
const hostTemp = process.platform === 'win32' ? tmpdir() : null
|
|
21
|
+
let compilerRoot = null
|
|
22
|
+
const compilerFailure = () => Object.assign(new Error('NATIVE_COMPILER_SCRATCH_UNAVAILABLE'), { code: 'NATIVE_COMPILER_SCRATCH_UNAVAILABLE' })
|
|
23
|
+
const sameDirectory = (info, expected) => info.isDirectory() && !info.isSymbolicLink() && info.dev === expected.dev && info.ino === expected.ino
|
|
24
|
+
const rootStamp = path => `dsh-native-compiler-v1:${basename(path)}\n`
|
|
25
|
+
|
|
26
|
+
function compilerDirectory() {
|
|
27
|
+
try {
|
|
28
|
+
if (!compilerRoot) {
|
|
29
|
+
if (inheritedCompilerRoot !== undefined) {
|
|
30
|
+
if (!isAbsolute(inheritedCompilerRoot) || inheritedCompilerRoot.length > 140 || !/^dshc-[a-f0-9]{16}$/.test(basename(inheritedCompilerRoot))) throw compilerFailure()
|
|
31
|
+
const info = lstatSync(inheritedCompilerRoot, { bigint: true })
|
|
32
|
+
if (!info.isDirectory() || info.isSymbolicLink() || realpathSync(inheritedCompilerRoot) !== inheritedCompilerRoot || readFileSync(join(inheritedCompilerRoot, '.dsh-root'), 'utf8') !== rootStamp(inheritedCompilerRoot)) throw compilerFailure()
|
|
33
|
+
compilerRoot = { path: inheritedCompilerRoot, info }
|
|
34
|
+
} else {
|
|
35
|
+
const parent = realpathSync(hostTemp)
|
|
36
|
+
const path = join(parent, `dshc-${randomBytes(8).toString('hex')}`)
|
|
37
|
+
if (path.length > 140) throw compilerFailure()
|
|
38
|
+
mkdirSync(path)
|
|
39
|
+
writeFileSync(join(path, '.dsh-root'), rootStamp(path), { flag: 'wx' })
|
|
40
|
+
compilerRoot = { path, info: lstatSync(path, { bigint: true }) }
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (!sameDirectory(lstatSync(compilerRoot.path, { bigint: true }), compilerRoot.info) || realpathSync(compilerRoot.path) !== compilerRoot.path) throw compilerFailure()
|
|
44
|
+
const path = mkdtempSync(join(compilerRoot.path, 'c-'))
|
|
45
|
+
const info = lstatSync(path, { bigint: true }), owner = randomBytes(16).toString('hex')
|
|
46
|
+
writeFileSync(join(path, '.dsh-owner'), owner, { flag: 'wx' })
|
|
47
|
+
const root = compilerRoot
|
|
48
|
+
// Never recursively remove a path obtained from the environment. Only this
|
|
49
|
+
// allocated child, after confirmed helper exit, with unchanged filesystem
|
|
50
|
+
// identity and no links/subdirectories, is eligible for flat cleanup.
|
|
51
|
+
const cleanup = async () => {
|
|
52
|
+
try {
|
|
53
|
+
if (dirname(path) !== root.path || !/^c-[A-Za-z0-9]{6}$/.test(basename(path))) return false
|
|
54
|
+
if (!sameDirectory(await lstat(root.path, { bigint: true }), root.info) || await realpath(root.path) !== root.path) return false
|
|
55
|
+
if (!sameDirectory(await lstat(path, { bigint: true }), info) || await realpath(path) !== path || await readFile(join(path, '.dsh-owner'), 'utf8') !== owner) return false
|
|
56
|
+
const names = await readdir(path)
|
|
57
|
+
if (names.length > 128) return false
|
|
58
|
+
for (const name of names) { const entry = await lstat(join(path, name)); if (!entry.isFile() || entry.isSymbolicLink()) return false }
|
|
59
|
+
for (const name of names) await unlink(join(path, name))
|
|
60
|
+
await rmdir(path)
|
|
61
|
+
return true
|
|
62
|
+
} catch { return false } // Busy, replaced or unknown resources remain.
|
|
63
|
+
}
|
|
64
|
+
return { root: root.path, path, cleanup }
|
|
65
|
+
} catch { throw compilerFailure() }
|
|
66
|
+
}
|
|
10
67
|
|
|
11
68
|
/** Deliberately small environment: profiles, credentials and proxy secrets are never inherited. */
|
|
12
69
|
export function privateEnvironment(home, source = process.env) {
|
|
@@ -17,6 +74,7 @@ export function privateEnvironment(home, source = process.env) {
|
|
|
17
74
|
for (const key of ['SystemRoot', 'windir', 'ComSpec', 'LANG', 'LC_ALL']) if (source[key]) env[key] = source[key]
|
|
18
75
|
// Fixed executable paths remove PATH lookup from both supervisor and bridge.
|
|
19
76
|
env.PATH = process.platform === 'win32' ? join(source.SystemRoot ?? 'C:\\Windows', 'System32') : '/usr/bin:/bin'
|
|
77
|
+
if (process.platform === 'win32' && (compilerRoot?.path ?? inheritedCompilerRoot)) env[COMPILER_ROOT] = compilerRoot?.path ?? inheritedCompilerRoot
|
|
20
78
|
return env
|
|
21
79
|
}
|
|
22
80
|
|
|
@@ -35,30 +93,35 @@ export async function resolveNativeHelper({ python = '/usr/bin/python3' } = {})
|
|
|
35
93
|
export function nativeProcess(helper, mode, spec, { home, env = privateEnvironment(home) } = {}) {
|
|
36
94
|
const events = new EventEmitter()
|
|
37
95
|
const args = helper.platform === 'win32' ? [...helper.prefix, '-Mode', mode] : [...helper.prefix, mode]
|
|
38
|
-
const
|
|
39
|
-
|
|
96
|
+
const compiler = helper.platform === 'win32' ? compilerDirectory() : null
|
|
97
|
+
const helperEnv = compiler ? Object.fromEntries(Object.entries(env).filter(([key]) => ![COMPILER_ROOT, COMPILER_SCRATCH].includes(key.toUpperCase()))) : env
|
|
98
|
+
if (compiler) { helperEnv[COMPILER_ROOT] = compiler.root; helperEnv[COMPILER_SCRATCH] = compiler.path }
|
|
99
|
+
const child = spawn(helper.executable, args, { cwd: home, env: helperEnv, windowsHide: true, shell: false, stdio: ['pipe', 'pipe', 'pipe'] })
|
|
100
|
+
let tail = '', buffer = '', bytes = 0, closed = false, treeStopped = false
|
|
40
101
|
const decoder = new StringDecoder('utf8'), cliDecoder = new StringDecoder('utf8')
|
|
41
|
-
|
|
102
|
+
const cliOutput = new NativeCliOutput()
|
|
42
103
|
const frame = value => {
|
|
104
|
+
if (mode === 'supervise' && value.control === 'stopped' && value.treeStopped === true) treeStopped = true
|
|
43
105
|
if (mode === 'supervise' && value.type === 'cli-output') {
|
|
44
106
|
if (typeof value.data !== 'string' || value.data.length > MAX_FRAME * 2) throw new Error('INVALID_CLI_FRAME')
|
|
45
|
-
|
|
46
|
-
if (Buffer.byteLength(cliBuffer) > MAX_FRAME) throw new Error('CLI_FRAME_LIMIT')
|
|
47
|
-
let end
|
|
48
|
-
while ((end = cliBuffer.indexOf('\n')) >= 0) {
|
|
49
|
-
const line = cliBuffer.slice(0, end); cliBuffer = cliBuffer.slice(end + 1)
|
|
50
|
-
if (line.trim()) events.emit('message', JSON.parse(line))
|
|
51
|
-
}
|
|
107
|
+
for (const message of cliOutput.push(cliDecoder.write(Buffer.from(value.data, 'base64')))) events.emit('message', message)
|
|
52
108
|
} else events.emit(value.control ? 'control' : 'message', value)
|
|
53
109
|
}
|
|
54
|
-
const exit = new Promise(resolve => child.once('close', (code, signal) => {
|
|
110
|
+
const exit = new Promise(resolve => child.once('close', async (code, signal) => {
|
|
111
|
+
closed = true
|
|
112
|
+
if (compiler && code === 0 && signal === null && (mode !== 'supervise' || treeStopped)) await compiler.cleanup()
|
|
113
|
+
events.emit('closed', { code, signal }); resolve({ code, signal })
|
|
114
|
+
}))
|
|
55
115
|
child.on('error', error => events.emit('failure', error))
|
|
56
116
|
child.stdin.on('error', () => {})
|
|
57
117
|
child.stderr.on('data', data => { tail = (tail + data.toString('utf8')).slice(-4096) })
|
|
58
118
|
child.stdout.on('data', chunk => {
|
|
59
119
|
bytes += chunk.length
|
|
60
120
|
buffer += decoder.write(chunk)
|
|
61
|
-
|
|
121
|
+
// MCP responses and CLI image echoes have their own bounded readers. Their
|
|
122
|
+
// retained connections can carry several screenshots without a raw lifetime cap.
|
|
123
|
+
const boundedStream = mode === 'client' || mode === 'server' || mode === 'supervise'
|
|
124
|
+
if (!boundedStream && bytes > 8 * 1024 * 1024 || Buffer.byteLength(buffer) > MAX_FRAME) { events.emit('failure', new Error('OUTPUT_LIMIT')); child.stdin.end(); return }
|
|
62
125
|
let end
|
|
63
126
|
while ((end = buffer.indexOf('\n')) >= 0) {
|
|
64
127
|
const line = buffer.slice(0, end); buffer = buffer.slice(end + 1)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const invalid = () => { throw Object.assign(new Error('请选择当前团队中的 Bot。'), { code: 'INVALID_BINDING_OWNER' }) }
|
|
2
|
+
|
|
3
|
+
/** A bounded owner view for chat settings; it never reads task inputs or receipts. */
|
|
4
|
+
export async function inspectProductBinding({ runtime, lifecycle, botSettings, fundingAccounts, signal }, payload) {
|
|
5
|
+
if (!payload || typeof payload !== 'object' || Array.isArray(payload) || Object.keys(payload).some(key => key !== 'botId') || typeof payload.botId !== 'string') invalid()
|
|
6
|
+
signal?.throwIfAborted()
|
|
7
|
+
await runtime.load()
|
|
8
|
+
signal?.throwIfAborted()
|
|
9
|
+
const bot = lifecycle.committedBot(payload.botId)
|
|
10
|
+
if (!bot) invalid()
|
|
11
|
+
const main = lifecycle.committedMainBotIds?.().includes(bot.id) === true
|
|
12
|
+
const record=botSettings.get(bot.id)
|
|
13
|
+
const grant=main?lifecycle.committedGrant?.(bot.id):null
|
|
14
|
+
return { schemaVersion: 1, bot: { id: bot.id, name: bot.name, role: bot.role ?? '', model: bot.model ?? null,
|
|
15
|
+
main, permissions: main ? 'full-control' : 'scoped',
|
|
16
|
+
appliedModel: typeof bot.appliedModel === 'string' ? bot.appliedModel : null },
|
|
17
|
+
record: grant?{...record,grant}:record, accounts: { status: 'available', items: fundingAccounts?.catalog() ?? [] },
|
|
18
|
+
availableActions: ['binding.save', 'funding.account.save'] }
|
|
19
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The panel-facing data actions. The human signs in as owner and picks which
|
|
3
|
+
* Bot's data to view; the read-model's dispatch already requires an
|
|
4
|
+
* authenticated owner and an allow-listed action, so these handlers only map
|
|
5
|
+
* payloads onto the engine. A Bot id is still validated by the engine (never a
|
|
6
|
+
* path, another service or an endpoint), and every failure is a structured
|
|
7
|
+
* DataError the panel can render instead of a silent empty state.
|
|
8
|
+
*
|
|
9
|
+
* Wire these into product-composition's `actions` and add their names to the
|
|
10
|
+
* read-model ACTIONS allow-list — see data-wiring.patch.
|
|
11
|
+
*
|
|
12
|
+
* Interface notes for the panel:
|
|
13
|
+
* - `data.show` takes `{ kind, table|sql, cardId? }`. With `cardId` it re-opens
|
|
14
|
+
* a SAVED card: the chart is re-rendered from its saved spec and the table
|
|
15
|
+
* from its saved result, so a chart card can be reopened (its id is a card
|
|
16
|
+
* id, never a table name).
|
|
17
|
+
* - `data.export` fails loudly: a library write that fails returns a structured
|
|
18
|
+
* error (output_too_large for the library's single-file limit) and NO path,
|
|
19
|
+
* so the panel must not report a completed export.
|
|
20
|
+
* - `data.cancel` reaches the Host and SIGKILLs the Bot's worker; it is a stop
|
|
21
|
+
* REQUEST, and the in-flight call fails with `cancelled`.
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import { DataFailure } from './bot-data-surface.mjs'
|
|
25
|
+
|
|
26
|
+
const errorOf = error => (error instanceof DataFailure ? error.error : { code: 'engine_unavailable', message: String(error?.message ?? error) })
|
|
27
|
+
|
|
28
|
+
/** @param {{ engine: object }} source */
|
|
29
|
+
export function createDataActions({ engine } = {}) {
|
|
30
|
+
if (!engine || typeof engine.forBot !== 'function') throw new TypeError('DATA_ACTIONS_REQUIRE_ENGINE')
|
|
31
|
+
const wrap = run => async payload => { try { return await run(payload) } catch (error) { return { error: errorOf(error) } } }
|
|
32
|
+
const bot = payload => engine.forBot(payload?.botId)
|
|
33
|
+
|
|
34
|
+
return Object.freeze({
|
|
35
|
+
'data.catalog': wrap(payload => bot(payload).catalog()),
|
|
36
|
+
'data.load': wrap(payload => bot(payload).load(payload)),
|
|
37
|
+
'data.describe': wrap(payload => bot(payload).describe(payload?.target)),
|
|
38
|
+
'data.sql': wrap(payload => bot(payload).sql(payload)),
|
|
39
|
+
'data.show': wrap(payload => bot(payload).show(payload)),
|
|
40
|
+
'data.page': wrap(payload => bot(payload).page(payload)),
|
|
41
|
+
'data.export': wrap(payload => bot(payload).exportCsv(payload)),
|
|
42
|
+
'data.remove': wrap(payload => bot(payload).remove(payload)),
|
|
43
|
+
'data.cancel': wrap(payload => bot(payload).cancel()),
|
|
44
|
+
})
|
|
45
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The chart compiler: a tiny, safe spec the model can ask for, compiled to a
|
|
3
|
+
* bounded SQL aggregation and then shaped into a declarative result the panel
|
|
4
|
+
* renders as inline SVG. The model never writes a chart grammar and never
|
|
5
|
+
* writes raw SQL for a chart — only {type,x,y,color,agg,…} with column names
|
|
6
|
+
* that must already exist. Identifiers are quoted; values are never
|
|
7
|
+
* concatenated into the SQL.
|
|
8
|
+
*
|
|
9
|
+
* Supported marks: bar, line, area (the required minimum). scatter, histogram,
|
|
10
|
+
* pie and heatmap are intentionally refused for now rather than faked — see
|
|
11
|
+
* data-report.md. Aggregations count/sum/avg/min/max are supported; median is
|
|
12
|
+
* refused (SQLite has no median aggregate) rather than approximated silently.
|
|
13
|
+
*
|
|
14
|
+
* Ported and narrowed from OpenMausBot server/data/chart-compiler.ts (1bc4749).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import { DATA_LIMITS, DataFailure, dataError, quoteIdent } from './bot-data-surface.mjs'
|
|
18
|
+
|
|
19
|
+
const fail = (code, message, extra = {}) => { throw new DataFailure(dataError(code, message, extra)) }
|
|
20
|
+
|
|
21
|
+
const MARKS = new Set(['bar', 'line', 'area'])
|
|
22
|
+
const AGGS = new Set(['count', 'sum', 'avg', 'min', 'max'])
|
|
23
|
+
const SORTS = new Set(['x', '-x', 'y', '-y'])
|
|
24
|
+
const TIME_FORMAT = { year: '%Y', quarter: null, month: '%Y-%m', week: '%Y-W%W', day: '%Y-%m-%d', hour: '%Y-%m-%d %H' }
|
|
25
|
+
|
|
26
|
+
/** Validate the spec against the table's real columns; throw spec_invalid otherwise. */
|
|
27
|
+
function validate(spec, columns) {
|
|
28
|
+
if (!spec || typeof spec !== 'object') fail('spec_invalid', 'A chart spec object is required.')
|
|
29
|
+
if (!MARKS.has(spec.type)) fail('spec_invalid', `Chart type ${JSON.stringify(spec.type)} is not supported yet. Supported: bar, line, area.`)
|
|
30
|
+
if (typeof spec.x !== 'string' || !columns.includes(spec.x)) fail('spec_invalid', `Unknown x column ${JSON.stringify(spec.x)}. Use data_describe to list columns.`)
|
|
31
|
+
if (spec.y !== undefined && (typeof spec.y !== 'string' || !columns.includes(spec.y))) fail('spec_invalid', `Unknown y column ${JSON.stringify(spec.y)}. Use data_describe to list columns.`)
|
|
32
|
+
if (spec.color !== undefined && (typeof spec.color !== 'string' || !columns.includes(spec.color))) fail('spec_invalid', `Unknown color column ${JSON.stringify(spec.color)}.`)
|
|
33
|
+
const agg = spec.agg ?? (spec.y ? 'sum' : 'count')
|
|
34
|
+
if (!AGGS.has(agg)) fail('spec_invalid', `Aggregation ${JSON.stringify(agg)} is not supported. Supported: ${[...AGGS].join(', ')}.`)
|
|
35
|
+
if (spec.sort !== undefined && !SORTS.has(spec.sort)) fail('spec_invalid', `Unknown sort ${JSON.stringify(spec.sort)}.`)
|
|
36
|
+
if (spec.timeUnit !== undefined && !(spec.timeUnit in TIME_FORMAT)) fail('spec_invalid', `Unknown timeUnit ${JSON.stringify(spec.timeUnit)}.`)
|
|
37
|
+
if (spec.timeUnit === 'quarter' && !spec.y) fail('spec_invalid', 'A quarter bucket needs an aggregation (set y and agg).')
|
|
38
|
+
return { agg }
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** Build the aggregation SQL and a reduction description. `from` is the final SQL relation (a quoted identifier or a parenthesised subquery); spec columns are quoted here, never concatenated raw. */
|
|
42
|
+
export function compileChart(spec, columns, from) {
|
|
43
|
+
const { agg } = validate(spec, columns)
|
|
44
|
+
const limit = Math.min(Math.max(1, Math.trunc(spec.limit ?? 20)), 1000)
|
|
45
|
+
const hasColor = spec.color !== undefined
|
|
46
|
+
const groupParts = []
|
|
47
|
+
const selectParts = []
|
|
48
|
+
|
|
49
|
+
// x expression: raw column, or a time bucket when timeUnit is set.
|
|
50
|
+
let xExpr
|
|
51
|
+
if (spec.timeUnit) {
|
|
52
|
+
const format = TIME_FORMAT[spec.timeUnit]
|
|
53
|
+
xExpr = spec.timeUnit === 'quarter'
|
|
54
|
+
? `(strftime('%Y', ${quoteIdent(spec.x)}) || '-Q' || ((CAST(strftime('%m', ${quoteIdent(spec.x)}) AS INTEGER) + 2) / 3))`
|
|
55
|
+
: `strftime(${`'${format}'`}, ${quoteIdent(spec.x)})`
|
|
56
|
+
groupParts.push(xExpr)
|
|
57
|
+
selectParts.push(`${xExpr} AS x`)
|
|
58
|
+
} else {
|
|
59
|
+
groupParts.push(quoteIdent(spec.x))
|
|
60
|
+
selectParts.push(`${quoteIdent(spec.x)} AS x`)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// y expression: COUNT(*) or AGG(y).
|
|
64
|
+
const yExpr = agg === 'count' || !spec.y ? 'COUNT(*)' : `${agg.toUpperCase()}(${quoteIdent(spec.y)})`
|
|
65
|
+
selectParts.push(`${yExpr} AS y`)
|
|
66
|
+
|
|
67
|
+
if (hasColor) { groupParts.push(quoteIdent(spec.color)); selectParts.push(`${quoteIdent(spec.color)} AS series`) }
|
|
68
|
+
|
|
69
|
+
let orderBy
|
|
70
|
+
switch (spec.sort) {
|
|
71
|
+
case '-x': orderBy = 'x DESC'; break
|
|
72
|
+
case 'y': orderBy = 'y ASC'; break
|
|
73
|
+
case '-y': orderBy = 'y DESC'; break
|
|
74
|
+
default: orderBy = 'x ASC'
|
|
75
|
+
}
|
|
76
|
+
const sql = `SELECT ${selectParts.join(', ')} FROM ${from} GROUP BY ${groupParts.join(', ')} ORDER BY ${orderBy} LIMIT ${limit}`
|
|
77
|
+
const reduction = {
|
|
78
|
+
method: spec.timeUnit ? 'timeBucket' : 'group',
|
|
79
|
+
inputRows: null,
|
|
80
|
+
outputRows: null,
|
|
81
|
+
note: spec.timeUnit ? `Bucketed by ${spec.timeUnit}.` : `Grouped by ${spec.x}${hasColor ? ` and ${spec.color}` : ''}, ${agg}${spec.y ? ` of ${spec.y}` : ''}. Top ${limit} by ${orderBy}.`,
|
|
82
|
+
}
|
|
83
|
+
return { sql, xLabel: spec.x, yLabel: spec.y ?? 'count', reduction, hasColor }
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Shape a bounded result (columns + rows) into a declarative chart the panel renders. */
|
|
87
|
+
export function shapeChart(result, spec) {
|
|
88
|
+
const hasColor = result.columns.some(column => column.name === 'series')
|
|
89
|
+
const seriesMap = new Map()
|
|
90
|
+
let maxMarks = DATA_LIMITS.chartMaxMarks
|
|
91
|
+
for (const row of result.rows) {
|
|
92
|
+
if (maxMarks-- <= 0) break
|
|
93
|
+
const x = row[0]
|
|
94
|
+
const y = row[1]
|
|
95
|
+
const key = hasColor ? String(row[2]) : 'series'
|
|
96
|
+
if (!seriesMap.has(key)) seriesMap.set(key, [])
|
|
97
|
+
seriesMap.get(key).push({ x: x === null ? null : String(x), y: typeof y === 'number' ? y : Number(y) || 0 })
|
|
98
|
+
}
|
|
99
|
+
const series = [...seriesMap.entries()].map(([key, points]) => ({ key, points }))
|
|
100
|
+
return {
|
|
101
|
+
kind: 'chart',
|
|
102
|
+
type: spec.type,
|
|
103
|
+
xLabel: spec.x,
|
|
104
|
+
yLabel: spec.y ?? 'count',
|
|
105
|
+
stacked: spec.stack === true,
|
|
106
|
+
series,
|
|
107
|
+
truncated: result.truncated || maxMarks < 0,
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The data context envelope (apps.data-context, P2): a metadata-only summary
|
|
3
|
+
* the Host can inject into a Bot's prompt so it knows what it can query,
|
|
4
|
+
* WITHOUT ever leaking row data. It lists table names, columns, types and row
|
|
5
|
+
* counts, plus saved card titles — never a single cell value.
|
|
6
|
+
*
|
|
7
|
+
* This is a pure function of the engine's catalog; the composition decides
|
|
8
|
+
* where to inject it (see data-wiring.patch). It is bounded so a Bot with many
|
|
9
|
+
* tables cannot bloat the prompt.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { DATA_LIMITS } from './bot-data-surface.mjs'
|
|
13
|
+
|
|
14
|
+
const TABLES_MAX = 25
|
|
15
|
+
const COLUMNS_MAX = 20
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {object} engine
|
|
19
|
+
* @param {string} botId
|
|
20
|
+
* @returns {Promise<{ tables: Array<{name:string,rowCount?:number,columns:string[]}>, cards: Array<{id:string,title:string,kind:string}> }>}
|
|
21
|
+
*/
|
|
22
|
+
export async function buildDataContext(engine, botId) {
|
|
23
|
+
const catalog = await engine.forBot(botId).catalog()
|
|
24
|
+
return {
|
|
25
|
+
tables: catalog.tables.slice(0, TABLES_MAX).map(table => ({
|
|
26
|
+
name: table.name,
|
|
27
|
+
columns: table.columns.slice(0, COLUMNS_MAX).map(column => `${column.name} ${column.type}`.trim()),
|
|
28
|
+
columnCount: table.columns.length,
|
|
29
|
+
})),
|
|
30
|
+
cards: catalog.cards.slice(0, DATA_LIMITS.sheetCardsMax).map(card => ({ id: card.id, title: card.title, kind: card.kind })),
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Render the envelope as compact prompt text. Metadata only — no cell values. */
|
|
35
|
+
export function renderDataContext(context) {
|
|
36
|
+
if (!context || !context.tables?.length) return ''
|
|
37
|
+
const lines = ['You have data tables you can query with data_describe, data_sql, data_show and data_export (metadata only; no rows are shown here):']
|
|
38
|
+
for (const table of context.tables) {
|
|
39
|
+
const columns = table.columns.length ? `: ${table.columns.join(', ')}` : ''
|
|
40
|
+
lines.push(`- ${table.name}${columns}`)
|
|
41
|
+
}
|
|
42
|
+
for (const card of context.cards ?? []) lines.push(`- saved ${card.kind} card "${card.title}" (${card.id})`)
|
|
43
|
+
return lines.join('\n')
|
|
44
|
+
}
|