Drkoh-wz/team-craft--packages-team-flowise-client ↗★ 1

@local/team-flowise-client

Client half of the Flowise-like multi-agent team plugin for DeepSeek Harness: a Settings section page, a session-header team activity panel, and a workflow DAG canvas. Bundled with tsdown into a DSH __ModuleLoader__ client bundle. 配合宿主端使用,为多智能体团队提供看板、活动面板及 DAG 画布界面。

パッケージ
@local/team-flowise-client
互換性
未検証
バージョン
0.1.0
ライセンス
MIT
最終更新
2026/09/28

インストール

検証済み bundle がないか、互換性チェックに失敗しています。先にリポジトリの説明を読んでください。 README 全文を読む ↗

ドキュメント

README 全文を読む ↗

@local/team-flowise-client

Browser half of the Flowise-like multi-agent team plugin. It contributes three surfaces to the DSH web shell and reads its data from the host half (@local/team-flowise) over JSON HTTP routes.

SurfaceSlotRegistration
Settings page (Overview / Agents / Workflows / DAG canvas / Tasks / Runs)settings.sectionid: team-flowise, order: 500
Session-header team activity panelconversation.session.header.actionsid: team-flowise-activity, order: 60
Workflow DAG canvas— (rendered inside the settings page's DAG tab)—

Build

npm install          # only tsdown is needed
npm run build        # tsdown -> dist/index.js (ESM, Node) + dist/client.js (DSH client bundle)
npm run verify       # executes both artifacts and asserts the contract

npm run verify is the acceptance check: it parses both artifacts, imports the Node half, asserts the route table / record reducers / DAG geometry, then executes the browser bundle against a stub window.__ModuleLoader__ and a stub require to prove the factory face is reachable and that apply registers both slot cells.

Why two outputs

The package has two halves that cannot share one module format.

  • dist/index.js — plain ESM for Node. Imports nothing, so import('@local/team-flowise-client') cannot fail on a missing peer. It re-exports the environment-independent contract: the frozen route table (ROUTES, matchRoute, routeUrl), the record reducers (pickAgent, pickWorkflow, pickTask, pickRun), the DAG solver (layoutDag, decorateDag), the slot descriptors (SETTINGS_SECTION, SESSION_HEADER_ACTION), and describeClient() for an inspectable summary.

  • dist/client.js — the DSH browser bundle. The client module system installs window.__ModuleLoader__ as a lazy CJS table: a bundle only registers a factory, and materialization (factory(require) -> exports) happens on first import. The emitted script is therefore a classic script of exactly this shape:

    window.__ModuleLoader__.load({
      id: "@local/team-flowise-client",
      factory: (require) => {
        var module = { exports: {} };
        var exports = module.exports;
        /* rolldown's CJS chunk */
        return module.exports;
      },
    });
    

    tsdown.config.mjs produces that with a rolldown renderChunk plugin, so the wrapper is part of the chunk bytes rolldown writes and there is no post-processing step that could drift from the build.

    The browser half ships without a source map, deliberately. renderChunk runs before rolldown appends its //# sourceMappingURL trailer, so an enabled map ends up with the trailer inside the factory body, and the wrapper also shifts every line of the chunk map by a constant. A map that points at the wrong lines is worse than no map, so sourcemap: false and the bundle ends cleanly at the factory's closing });.

React and the shell's shared packages (react-dom, @deepseek-ai/dsh-client-ui-slots, @deepseek-ai/dsh-client-ui-primitives, …) stay external: they are platform seeds the shell injects into require, so bundling a second copy would split React's instance identity. dsh.client.external is intentionally empty — every needed name is in the seed table, and naming a package that is not in the graph only makes graph ordering harder to reason about.

Data flow

There is no harness.handle / host.call bridge here: the host is a composed cordis bundle, not a dynamic package sandbox, so no such channel exists. Data crosses as JSON over the WebServer routes the host registers under /api/team-flowise (@deepseek-ai/dsh-host-webserver, injected as webServer).

The route table is frozen in src/contract/routes.js and mirrors the host's registrations one-for-one. All writes are loopback-fenced on the host side.

Layout

src/
  contract/            environment-free: shared verbatim by both halves
    routes.js          the frozen HTTP route table
    domain.js          record reducers + status vocabularies
    layout.js          deterministic DAG layout (waves + barycenter pass)
    panels.js          slot contribution descriptors
  node/index.js        Node entry (imports nothing)
  client/
    index.js           plugin face: apply() registers both slot cells
    api.js             the only module that touches fetch
    store.js           shared module-level store (both surfaces read it)
    context.js         React context + useSyncExternalStore / polling hooks
    styles.js          one CSS string, injected as a tagged 
    palette.js         canvas colours resolved from live theme tokens
    locales.js         zh/en dictionaries
    ui.js              presentational primitives
    components/
      settings-section.js
      activity-panel.js
      dag-canvas.js
scripts/verify.mjs     build + load verification

The store is module-scoped on purpose: the client module system materializes a package's factory once per page, so the settings page and the header panel — two different branches of the React tree — genuinely share one store, and polling lives in the store rather than in either component.

Conventions this package follows

  • No JSX, no TypeScript, no bundler magic. React.createElement only, so what tsdown emits is what the browser runs. React is imported as a namespace (import * as React from 'react'), not as named imports: the platform seed is a CJS module object, and a named import would not survive the interop.
  • Every side effect is owned by the fiber. The stylesheet, both slot registrations, and the locale dictionaries are declared through ctx.effect(...) / slots.inject(...), so stopping or updating the plugin removes all of them.
  • Live host records never reach React state. Each pick* reducer copies only the scalars the UI draws, so a large node payload cannot land in a component.
  • All colour comes from --dsw-alias-* theme tokens with light-theme fallbacks, so the surfaces stay readable under the dark theme. The canvas resolves those tokens at paint time (palette.js) because a `` cannot inherit CSS custom properties.

Linking it into a profile

See SETUP.md. The short version: the profile must depend on this package so the host loader can resolve it, and a restart is required — dsh.client package metadata is cached per package name and never re-read.