@wenrwa/marketplace-cli 0.8.2 → 0.8.3

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.
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ /**
40
+ * oc-27 — the ACTUAL local launch must carry the same keys the hosted config does:
41
+ * `plugin` (activity, titles, Needs-you, session-id capture), `mcp.wenrwa-marketplace`
42
+ * (when a connect token exists) and `theme`. A builder-only test missed this: the
43
+ * builder was fine, the local call sites never fed it a plugin or a token.
44
+ */
45
+ const fs = __importStar(require("fs"));
46
+ const path = __importStar(require("path"));
47
+ const url_1 = require("url");
48
+ const ws_1 = __importDefault(require("ws"));
49
+ const agentLaunch_1 = require("../bridge/agentLaunch");
50
+ const server_1 = require("../bridge/server");
51
+ const sessionManager_1 = require("../bridge/sessionManager");
52
+ const hosted = require(path.join(__dirname, '..', '..', '..', 'infra', 'terminal-image', 'opencode', 'build-config.js'));
53
+ const GW = 'https://api.example.test/api/v1/opencode/v1';
54
+ const oc = { engine: 'opencode', model: 'moonshotai/kimi-k2', gatewayUrl: GW, gatewayToken: 'hgw_abc' };
55
+ const cfgOf = (l) => JSON.parse(l.env.OPENCODE_CONFIG_CONTENT);
56
+ // The shape cli/src/commands/bridge.ts hands resolveAgentLaunch (mcpInstall + bridgeApiUrl).
57
+ const realDeps = {
58
+ mcpServer: { command: '/usr/bin/node', args: ['/h/.wen-market/mcp/dist/index.js'] },
59
+ apiUrl: 'https://api.example.test/api/v1',
60
+ activity: { settingsPath: '/h/.wen-market/hiveop-settings.json', sessionId: 'a1', activityFile: '/h/.wen-market/activity.jsonl' },
61
+ sessionPin: { agentId: 'a1', exists: false },
62
+ };
63
+ describe('local OpenCode launch carries the hosted keys', () => {
64
+ const hostedCfg = hosted.buildConfig({
65
+ WENRWA_AGENT_MODEL: oc.model, HIVEOP_GATEWAY_URL: GW, HIVEOP_GATEWAY_TOKEN: 't', WENRWA_CONNECT_TOKEN: 'c',
66
+ });
67
+ it('plugin is a file:// URL to a file that exists in the installed package', () => {
68
+ const cfg = cfgOf((0, agentLaunch_1.resolveAgentLaunch)({ opencode: oc, connectToken: 'c', ...realDeps }));
69
+ expect(cfg.plugin).toHaveLength(1);
70
+ expect(cfg.plugin[0]).toMatch(/^file:\/\//);
71
+ expect(fs.existsSync((0, url_1.fileURLToPath)(cfg.plugin[0]))).toBe(true);
72
+ expect(path.basename((0, url_1.fileURLToPath)(cfg.plugin[0]))).toBe('opencode-plugin.mjs');
73
+ });
74
+ it('mcp.wenrwa-marketplace is present with the token by reference only', () => {
75
+ const l = (0, agentLaunch_1.resolveAgentLaunch)({ opencode: oc, connectToken: 'secret-conn-token', ...realDeps });
76
+ expect(cfgOf(l).mcp['wenrwa-marketplace'].environment.WENRWA_CONNECT_TOKEN).toBe('{env:WENRWA_CONNECT_TOKEN}');
77
+ expect(l.env.OPENCODE_CONFIG_CONTENT).not.toContain('secret-conn-token');
78
+ expect(l.env.WENRWA_CONNECT_TOKEN).toBe('secret-conn-token');
79
+ });
80
+ it('env carries HIVEOP_GATEWAY_URL so the plugin can report the session id (resume)', () => {
81
+ const l = (0, agentLaunch_1.resolveAgentLaunch)({ opencode: oc, connectToken: 'c', ...realDeps });
82
+ expect(l.env.HIVEOP_GATEWAY_URL).toBe(GW);
83
+ expect(l.env.HIVEOP_GATEWAY_TOKEN).toBe('hgw_abc');
84
+ });
85
+ it('theme matches the hosted config (terminal palette, no own background)', () => {
86
+ const cfg = cfgOf((0, agentLaunch_1.resolveAgentLaunch)({ opencode: oc, ...realDeps }));
87
+ expect(cfg.theme).toBe('system');
88
+ expect(cfg.theme).toBe(hostedCfg.theme);
89
+ });
90
+ it('the same top-level keys as hosted (modulo the hosted-only plugin path)', () => {
91
+ const local = cfgOf((0, agentLaunch_1.resolveAgentLaunch)({ opencode: oc, connectToken: 'c', ...realDeps }));
92
+ const keys = (o) => Object.keys(o).filter((k) => k !== 'instructions').sort();
93
+ expect(keys(local)).toEqual(keys(hostedCfg));
94
+ });
95
+ });
96
+ describe('loopback open (real bridge wiring) falls back to the bridge-config connect token', () => {
97
+ let handle;
98
+ let spawns;
99
+ beforeEach(async () => {
100
+ spawns = [];
101
+ const pty = { write() { }, resize() { }, kill() { }, onData() { }, onExit() { } };
102
+ handle = await (0, server_1.startBridgeServer)({
103
+ sessionToken: 'tok', allowedOrigin: 'https://app.hiveop.io',
104
+ sessions: new sessionManager_1.SessionManager({ spawn: (o) => { spawns.push(o); return pty; } }),
105
+ resolveLocalAgentCwd: () => '/tmp/proj',
106
+ commandExists: () => true,
107
+ activityFile: '/h/activity.jsonl', hiveOpSettingsPath: '/h/settings.json',
108
+ mcpServer: realDeps.mcpServer, mcpApiUrl: realDeps.apiUrl,
109
+ connectToken: 'bridge-cfg-token',
110
+ });
111
+ });
112
+ afterEach(async () => { await handle.close(); });
113
+ it('open frame without connectToken still yields plugin + mcp + theme', async () => {
114
+ const ws = new ws_1.default(`ws://127.0.0.1:${handle.port}`, { headers: { origin: 'https://app.hiveop.io' } });
115
+ await new Promise((r) => ws.on('open', r));
116
+ ws.send(JSON.stringify({ v: 1, token: 'tok' }));
117
+ const opened = new Promise((r) => ws.on('message', (m) => { if (JSON.parse(String(m)).t === 'opened')
118
+ r(null); }));
119
+ ws.send(JSON.stringify({ t: 'open', cols: 80, rows: 24, agentId: 'a1', workspaceId: 'w1', opencode: oc }));
120
+ await opened;
121
+ ws.close();
122
+ const cfg = cfgOf({ env: spawns[0].env });
123
+ expect(cfg.plugin[0]).toMatch(/^file:\/\//);
124
+ expect(cfg.mcp['wenrwa-marketplace']).toBeDefined();
125
+ expect(cfg.theme).toBe('system');
126
+ expect(spawns[0].env.WENRWA_CONNECT_TOKEN).toBe('bridge-cfg-token');
127
+ expect(spawns[0].env.OPENCODE_CONFIG_CONTENT).not.toContain('bridge-cfg-token');
128
+ });
129
+ });
@@ -4,6 +4,7 @@ exports.HIVEOP_CONTEXT_ENV_VALUE = exports.HIVEOP_CONTEXT_ENV_VAR = void 0;
4
4
  exports.missingCommandMessage = missingCommandMessage;
5
5
  exports.resolveAgentLaunch = resolveAgentLaunch;
6
6
  const localContextWriter_1 = require("./localContextWriter");
7
+ const opencodePlugin_1 = require("./opencodePlugin");
7
8
  const opencodeConfig_1 = require("./opencodeConfig");
8
9
  /** lws-08 — env var name a spawned `claude` (or any tooling inspecting its
9
10
  * own environment) can read to find the pushed context manifest. */
@@ -46,21 +47,27 @@ function resolveOpencodeLaunch(opts, oc) {
46
47
  const args = [];
47
48
  if ((0, opencodeConfig_1.isCapturedOpencodeSessionId)(oc.sessionId))
48
49
  args.push('-s', oc.sessionId);
49
- const config = (0, opencodeConfig_1.buildOpencodeConfig)({
50
- model: oc.model,
51
- gatewayBaseUrl: oc.gatewayUrl,
52
- autonomous: !!opts.autonomous,
53
- withMcp: !!opts.connectToken,
54
- // oc-23: Claude loads .hiveop/context.md via its SessionStart hook; OpenCode has none, so it reads it as instructions.
55
- instructions: [exports.HIVEOP_CONTEXT_ENV_VALUE],
56
- ...(opts.mcpServer ? { mcpCommand: [opts.mcpServer.command, ...opts.mcpServer.args] } : {}),
57
- ...(opts.apiUrl ? { mcpEnvPassthrough: ['MARKETPLACE_API_URL'] } : {}),
58
- });
50
+ const config = {
51
+ ...(0, opencodeConfig_1.buildOpencodeConfig)({
52
+ model: oc.model,
53
+ gatewayBaseUrl: oc.gatewayUrl,
54
+ autonomous: !!opts.autonomous,
55
+ withMcp: !!opts.connectToken,
56
+ // oc-23: Claude loads .hiveop/context.md via its SessionStart hook; OpenCode has none, so it reads it as instructions.
57
+ instructions: [exports.HIVEOP_CONTEXT_ENV_VALUE],
58
+ ...(opts.mcpServer ? { mcpCommand: [opts.mcpServer.command, ...opts.mcpServer.args] } : {}),
59
+ ...(opts.apiUrl ? { mcpEnvPassthrough: ['MARKETPLACE_API_URL'] } : {}),
60
+ }),
61
+ // oc-27: the HiveOp plugin (activity, titles, Needs-you, session-id capture) — as hosted does.
62
+ ...(0, opencodePlugin_1.buildOpenCodePluginConfig)(),
63
+ };
59
64
  const env = {
60
65
  [exports.HIVEOP_CONTEXT_ENV_VAR]: exports.HIVEOP_CONTEXT_ENV_VALUE,
61
66
  ...opencodeConfig_1.OPENCODE_QUIET_ENV,
62
67
  OPENCODE_CONFIG_CONTENT: JSON.stringify(config),
63
68
  [opencodeConfig_1.OPENCODE_GATEWAY_TOKEN_ENV]: oc.gatewayToken,
69
+ // oc-27: the plugin POSTs the captured session id to <gateway>/hiveop/session (resume).
70
+ HIVEOP_GATEWAY_URL: oc.gatewayUrl,
64
71
  };
65
72
  if (opts.connectToken)
66
73
  env.WENRWA_CONNECT_TOKEN = opts.connectToken;
@@ -16,6 +16,7 @@ export declare const OPENCODE_MIN_VERSION = "1.18.35";
16
16
  export declare const OPENCODE_INSTALL_HINT = "Install OpenCode: npm i -g opencode-ai@>=1.18.35";
17
17
  /** Every outbound call OpenCode makes at startup besides the gateway (oc-04 s5). */
18
18
  export declare const OPENCODE_QUIET_ENV: Readonly<Record<string, string>>;
19
+ export declare const OPENCODE_THEME = "system";
19
20
  export declare const OPENCODE_PROVIDER_ID = "hiveop";
20
21
  export declare const OPENCODE_GATEWAY_TOKEN_ENV = "HIVEOP_GATEWAY_TOKEN";
21
22
  export interface OpencodeConfigInput {
@@ -10,7 +10,7 @@
10
10
  * (`{env:HIVEOP_GATEWAY_TOKEN}`) so it never appears inside the JSON.
11
11
  */
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.isCapturedOpencodeSessionId = exports.OPENCODE_GATEWAY_TOKEN_ENV = exports.OPENCODE_PROVIDER_ID = exports.OPENCODE_QUIET_ENV = exports.OPENCODE_INSTALL_HINT = exports.OPENCODE_MIN_VERSION = exports.OPENCODE_PINNED_VERSION = void 0;
13
+ exports.isCapturedOpencodeSessionId = exports.OPENCODE_GATEWAY_TOKEN_ENV = exports.OPENCODE_PROVIDER_ID = exports.OPENCODE_THEME = exports.OPENCODE_QUIET_ENV = exports.OPENCODE_INSTALL_HINT = exports.OPENCODE_MIN_VERSION = exports.OPENCODE_PINNED_VERSION = void 0;
14
14
  exports.buildOpencodeConfig = buildOpencodeConfig;
15
15
  exports.opencodeVersionOk = opencodeVersionOk;
16
16
  /** Oldest OpenCode the local lane accepts. 1.18.35 is the version oc-04 verified
@@ -29,6 +29,7 @@ exports.OPENCODE_QUIET_ENV = Object.freeze({
29
29
  OPENCODE_DISABLE_TERMINAL_TITLE: '1',
30
30
  npm_config_offline: 'true',
31
31
  });
32
+ exports.OPENCODE_THEME = 'system';
32
33
  exports.OPENCODE_PROVIDER_ID = 'hiveop';
33
34
  exports.OPENCODE_GATEWAY_TOKEN_ENV = 'HIVEOP_GATEWAY_TOKEN';
34
35
  function buildOpencodeConfig(input) {
@@ -41,6 +42,9 @@ function buildOpencodeConfig(input) {
41
42
  model: `${exports.OPENCODE_PROVIDER_ID}/${model}`,
42
43
  // OpenCode makes a second, billed "title" call on the small model.
43
44
  small_model: `${exports.OPENCODE_PROVIDER_ID}/${model}`,
45
+ // oc-27: OpenCode's built-in "system" theme derives its palette from the terminal and
46
+ // leaves the background transparent, so the pane blends with the canvas like Claude's.
47
+ theme: exports.OPENCODE_THEME,
44
48
  provider: {
45
49
  [exports.OPENCODE_PROVIDER_ID]: {
46
50
  npm: '@ai-sdk/openai-compatible',
@@ -244,6 +244,9 @@ export interface BridgeServerOpts {
244
244
  args: string[];
245
245
  };
246
246
  mcpApiUrl?: string;
247
+ /** oc-27 — the bridge's own stored Connect Token: the fallback for an `open` frame that carries none
248
+ * (loopback frames from the browser never do), so local OpenCode agents get the same MCP as Claude. */
249
+ connectToken?: string;
247
250
  /**
248
251
  * rival-10 — every file touch of a LOCAL WORKSPACE AGENT (an `open` with
249
252
  * agentId + workspaceId), handed on for the ranked rival feed. The hook
@@ -736,7 +736,7 @@ function startBridgeServer(opts) {
736
736
  let launch = (0, agentLaunch_1.resolveAgentLaunch)({
737
737
  autonomous: !!frame.autonomous,
738
738
  ...(frame.opencode ? { opencode: frame.opencode } : {}),
739
- ...(frame.connectToken ? { connectToken: frame.connectToken } : {}),
739
+ ...((frame.connectToken || opts.connectToken) ? { connectToken: (frame.connectToken || opts.connectToken) } : {}),
740
740
  ...(opts.mcpServer ? { mcpServer: opts.mcpServer } : {}),
741
741
  ...(opts.mcpApiUrl ? { apiUrl: opts.mcpApiUrl } : {}),
742
742
  ...(cwd ? { sessionPin: { agentId, exists: agentSessionExists } } : {}),
@@ -1127,6 +1127,8 @@ exports.bridgeCommand = new commander_1.Command('bridge')
1127
1127
  hiveOpSettingsPath,
1128
1128
  ...(mcpInstall.ok ? { mcpServer: { command: mcpInstall.command, args: mcpInstall.args } } : {}),
1129
1129
  mcpApiUrl: bridgeApiUrl(),
1130
+ // oc-27: local OpenCode panes get the HiveOp MCP with the same token Claude's registration uses.
1131
+ connectToken: config.connectToken,
1130
1132
  // tchp-18: the loopback changes reporter is opt-in; without this the
1131
1133
  // tchp-12 machinery never constructs on a laptop and local panels sit
1132
1134
  // on "Waiting for changes…" forever.
@@ -1353,7 +1355,7 @@ exports.bridgeCommand = new commander_1.Command('bridge')
1353
1355
  resolveLaunch: ({ sessionId, opencode, connectToken }) => (0, agentLaunch_1.resolveAgentLaunch)({
1354
1356
  autonomous: true,
1355
1357
  ...(opencode ? { opencode } : {}),
1356
- ...(connectToken ? { connectToken } : {}),
1358
+ ...((connectToken || config.connectToken) ? { connectToken: (connectToken || config.connectToken) } : {}),
1357
1359
  ...(mcpInstall.ok ? { mcpServer: { command: mcpInstall.command, args: mcpInstall.args } } : {}),
1358
1360
  apiUrl: bridgeApiUrl(),
1359
1361
  ...(activityFile && hiveOpSettingsPath && sessionId
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wenrwa/marketplace-cli",
3
- "version": "0.8.2",
3
+ "version": "0.8.3",
4
4
  "description": "CLI tool for the Wenrwa Agent Marketplace — monitor bounties, agents, workspaces, and treasury from your terminal",
5
5
  "author": "Wenrwa <dev@wenrwa.com>",
6
6
  "license": "MIT",