@mycadet/cli 0.13.0-dev.202610171626.d97b8b8 → 0.13.0-dev.202610181631.3760abb

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.
@@ -60,10 +60,6 @@ import { GenerationHandoffEventSchema } from "./events/generation-handoff.js";
60
60
  import { HeartbeatConversationCreatedEventSchema } from "./events/heartbeat-conversation-created.js";
61
61
  import { HomeFeedUpdatedEventSchema } from "./events/home-feed-updated.js";
62
62
  import { HookEventSchema } from "./events/hook-event.js";
63
- import {
64
- HostAppControlCancelEventSchema,
65
- HostAppControlRequestEventSchema,
66
- } from "./events/host-app-control.js";
67
63
  import {
68
64
  HostBashCancelEventSchema,
69
65
  HostBashRequestEventSchema,
@@ -418,16 +414,6 @@ export {
418
414
  HookEventOwnerSchema,
419
415
  HookEventSchema,
420
416
  } from "./events/hook-event.js";
421
- export {
422
- type HostAppControlCancelEvent,
423
- HostAppControlCancelEventSchema,
424
- type HostAppControlInput,
425
- HostAppControlInputSchema,
426
- type HostAppControlRequestEvent,
427
- HostAppControlRequestEventSchema,
428
- type HostAppControlSequenceStep,
429
- HostAppControlSequenceStepSchema,
430
- } from "./events/host-app-control.js";
431
417
  export {
432
418
  type HostBashCancelEvent,
433
419
  HostBashCancelEventSchema,
@@ -1061,8 +1047,6 @@ export const AssistantEventSchema = z.discriminatedUnion("type", [
1061
1047
  HeartbeatConversationCreatedEventSchema,
1062
1048
  HomeFeedUpdatedEventSchema,
1063
1049
  HookEventSchema,
1064
- HostAppControlCancelEventSchema,
1065
- HostAppControlRequestEventSchema,
1066
1050
  HostBashCancelEventSchema,
1067
1051
  HostBashRequestEventSchema,
1068
1052
  HostBrowserCancelEventSchema,
@@ -2,7 +2,9 @@
2
2
  * Pins the environment-to-cloud-hub mapping in one place. Both consumers
3
3
  * (the Capacitor shell's `server.url` and the CLI remote-web edge's
4
4
  * `hubUrl`) read this helper, so this matrix is the single behavioral pin
5
- * for the served URLs.
5
+ * for the served URLs. (The remote-web edge additionally folds local → dev
6
+ * at its own site: clients served through a tunnel cannot reach the local
7
+ * seed's loopback.)
6
8
  */
7
9
 
8
10
  import { describe, expect, test } from "bun:test";
@@ -10,29 +12,19 @@ import { describe, expect, test } from "bun:test";
10
12
  import { cloudAssistantHubUrl, SEEDS } from "../index.js";
11
13
 
12
14
  describe("cloudAssistantHubUrl", () => {
13
- test("cloud environments resolve to their own web origin", () => {
14
- expect(cloudAssistantHubUrl("production")).toBe(
15
- "https://mycadet.ai/assistant",
16
- );
17
- expect(cloudAssistantHubUrl("staging")).toBe(
18
- "https://staging.mycadet.ai/assistant",
19
- );
20
- });
21
-
22
- test("every other environment falls back to the dev SPA", () => {
23
- for (const name of ["dev", "test", "local", "unknown-env", undefined]) {
15
+ test("every known environment resolves to its own web origin", () => {
16
+ for (const name of ["production", "staging", "dev", "test", "local"]) {
24
17
  expect(cloudAssistantHubUrl(name)).toBe(
25
- "https://dev.mycadet.ai/assistant",
18
+ `${SEEDS[name].webUrl}/assistant`,
26
19
  );
27
20
  }
28
21
  });
29
22
 
30
- test("cloud hub URLs derive from the seed web URLs", () => {
31
- for (const name of ["production", "staging"]) {
23
+ test("unknown environments fall back to the dev SPA", () => {
24
+ for (const name of ["unknown-env", undefined]) {
32
25
  expect(cloudAssistantHubUrl(name)).toBe(
33
- `${SEEDS[name].webUrl}/assistant`,
26
+ "https://dev.mycadet.ai/assistant",
34
27
  );
35
28
  }
36
- expect(cloudAssistantHubUrl("local")).toBe(`${SEEDS.dev.webUrl}/assistant`);
37
29
  });
38
30
  });
@@ -26,15 +26,11 @@ function portBlock(base: number): PortMap {
26
26
 
27
27
  /**
28
28
  * Base URL of the cloud-hosted assistant SPA (the "hub") for a deployment
29
- * environment. The Capacitor mobile shell bakes this into native builds as
30
- * `server.url`, and the CLI's remote-web edge stamps it into the served
31
- * config as `hubUrl`, so the environment-to-hub mapping lives here exactly
32
- * once.
33
- *
34
- * Only the cloud deployments (production, staging) serve the hosted SPA at
35
- * their own web origin; every other environment (dev, test, local, unknown)
36
- * falls back to the dev SPA, whose host serves remote clients that cannot
37
- * reach a local or per-developer web URL.
29
+ * environment: always `${SEEDS[env].webUrl}/assistant`. The Capacitor mobile
30
+ * shell bakes this into native builds as `server.url`, and the CLI's
31
+ * remote-web edge stamps it into the served config as `hubUrl`, so the
32
+ * environment-to-hub mapping lives here exactly once. Unknown environment
33
+ * names fall back to the dev SPA defensively.
38
34
  *
39
35
  * The `/assistant` suffix is deliberate: booting on the bare host lands on
40
36
  * the marketing page, whose CTA redirects to `mycadet.ai/assistant` and
@@ -46,10 +42,7 @@ function portBlock(base: number): PortMap {
46
42
  * imports type-only so it stays loadable on its own.
47
43
  */
48
44
  export function cloudAssistantHubUrl(envName: string | undefined): string {
49
- const seed =
50
- envName === "production" || envName === "staging"
51
- ? SEEDS[envName]
52
- : SEEDS.dev;
45
+ const seed = (envName && SEEDS[envName]) || SEEDS.dev;
53
46
  return `${seed.webUrl}/assistant`;
54
47
  }
55
48
 
@@ -2,7 +2,9 @@
2
2
  * Pins the environment-to-cloud-hub mapping in one place. Both consumers
3
3
  * (the Capacitor shell's `server.url` and the CLI remote-web edge's
4
4
  * `hubUrl`) read this helper, so this matrix is the single behavioral pin
5
- * for the served URLs.
5
+ * for the served URLs. (The remote-web edge additionally folds local → dev
6
+ * at its own site: clients served through a tunnel cannot reach the local
7
+ * seed's loopback.)
6
8
  */
7
9
 
8
10
  import { describe, expect, test } from "bun:test";
@@ -10,29 +12,19 @@ import { describe, expect, test } from "bun:test";
10
12
  import { cloudAssistantHubUrl, SEEDS } from "../index.js";
11
13
 
12
14
  describe("cloudAssistantHubUrl", () => {
13
- test("cloud environments resolve to their own web origin", () => {
14
- expect(cloudAssistantHubUrl("production")).toBe(
15
- "https://mycadet.ai/assistant",
16
- );
17
- expect(cloudAssistantHubUrl("staging")).toBe(
18
- "https://staging.mycadet.ai/assistant",
19
- );
20
- });
21
-
22
- test("every other environment falls back to the dev SPA", () => {
23
- for (const name of ["dev", "test", "local", "unknown-env", undefined]) {
15
+ test("every known environment resolves to its own web origin", () => {
16
+ for (const name of ["production", "staging", "dev", "test", "local"]) {
24
17
  expect(cloudAssistantHubUrl(name)).toBe(
25
- "https://dev.mycadet.ai/assistant",
18
+ `${SEEDS[name].webUrl}/assistant`,
26
19
  );
27
20
  }
28
21
  });
29
22
 
30
- test("cloud hub URLs derive from the seed web URLs", () => {
31
- for (const name of ["production", "staging"]) {
23
+ test("unknown environments fall back to the dev SPA", () => {
24
+ for (const name of ["unknown-env", undefined]) {
32
25
  expect(cloudAssistantHubUrl(name)).toBe(
33
- `${SEEDS[name].webUrl}/assistant`,
26
+ "https://dev.mycadet.ai/assistant",
34
27
  );
35
28
  }
36
- expect(cloudAssistantHubUrl("local")).toBe(`${SEEDS.dev.webUrl}/assistant`);
37
29
  });
38
30
  });
@@ -26,15 +26,11 @@ function portBlock(base: number): PortMap {
26
26
 
27
27
  /**
28
28
  * Base URL of the cloud-hosted assistant SPA (the "hub") for a deployment
29
- * environment. The Capacitor mobile shell bakes this into native builds as
30
- * `server.url`, and the CLI's remote-web edge stamps it into the served
31
- * config as `hubUrl`, so the environment-to-hub mapping lives here exactly
32
- * once.
33
- *
34
- * Only the cloud deployments (production, staging) serve the hosted SPA at
35
- * their own web origin; every other environment (dev, test, local, unknown)
36
- * falls back to the dev SPA, whose host serves remote clients that cannot
37
- * reach a local or per-developer web URL.
29
+ * environment: always `${SEEDS[env].webUrl}/assistant`. The Capacitor mobile
30
+ * shell bakes this into native builds as `server.url`, and the CLI's
31
+ * remote-web edge stamps it into the served config as `hubUrl`, so the
32
+ * environment-to-hub mapping lives here exactly once. Unknown environment
33
+ * names fall back to the dev SPA defensively.
38
34
  *
39
35
  * The `/assistant` suffix is deliberate: booting on the bare host lands on
40
36
  * the marketing page, whose CTA redirects to `mycadet.ai/assistant` and
@@ -46,10 +42,7 @@ function portBlock(base: number): PortMap {
46
42
  * imports type-only so it stays loadable on its own.
47
43
  */
48
44
  export function cloudAssistantHubUrl(envName: string | undefined): string {
49
- const seed =
50
- envName === "production" || envName === "staging"
51
- ? SEEDS[envName]
52
- : SEEDS.dev;
45
+ const seed = (envName && SEEDS[envName]) || SEEDS.dev;
53
46
  return `${seed.webUrl}/assistant`;
54
47
  }
55
48
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mycadet/cli",
3
- "version": "0.13.0-dev.202610171626.d97b8b8",
3
+ "version": "0.13.0-dev.202610181631.3760abb",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/vargasjr-dev/mycadet-temp.git"
@@ -1269,11 +1269,19 @@ export async function startRemoteWebIngress(opts: {
1269
1269
  ) {
1270
1270
  listenPort = recorded.listenPort;
1271
1271
  }
1272
+ // The hub mapping is per-environment, but every client served by THIS edge
1273
+ // is remote (they arrived through the tunnel) and cannot reach a
1274
+ // developer's loopback — so a local environment serves the dev hub, whose
1275
+ // host is reachable from anywhere.
1276
+ const currentEnvName = getCurrentEnvironment().name;
1277
+ const hubUrl = cloudAssistantHubUrl(
1278
+ currentEnvName === "local" ? "dev" : currentEnvName,
1279
+ );
1272
1280
  // The SPA config the served index must carry, computed up front so the
1273
1281
  // reuse decision and the actual spawn share one value and cannot drift.
1274
1282
  const spaOptions = includeWebApp
1275
1283
  ? {
1276
- hubUrl: cloudAssistantHubUrl(getCurrentEnvironment().name),
1284
+ hubUrl,
1277
1285
  ...(opts.assistantName ? { assistantName: opts.assistantName } : {}),
1278
1286
  ...(opts.assistantId ? { assistantId: opts.assistantId } : {}),
1279
1287
  }
@@ -1,146 +0,0 @@
1
- /**
2
- * Host app-control proxy SSE events (`host_app_control_request` /
3
- * `host_app_control_cancel`).
4
- *
5
- * Server → client instructions that proxy app-control actions (start,
6
- * observe, press, combo, sequence, type, click, drag, stop) to the desktop
7
- * client, targeting a specific application by bundle ID or process name. The
8
- * client executes the action and POSTs the result back to
9
- * `/v1/host-app-control-result`. `host_app_control_cancel` withdraws an
10
- * in-flight request.
11
- *
12
- * Canonical wire-contract source. Daemon code imports the types
13
- * directly from this file; external consumers import via
14
- * `@mycadet/assistant-api`.
15
- */
16
-
17
- import { z } from "zod";
18
-
19
- const HostAppControlStartInputSchema = z.object({
20
- tool: z.literal("start"),
21
- /** Bundle ID (preferred) or process name. */
22
- app: z.string(),
23
- /** Optional command-line arguments to launch the app with. */
24
- args: z.array(z.string()).optional(),
25
- });
26
-
27
- const HostAppControlObserveInputSchema = z.object({
28
- tool: z.literal("observe"),
29
- app: z.string(),
30
- /** Milliseconds to wait before capturing the window (default ~200ms). */
31
- settle_ms: z.number().optional(),
32
- });
33
-
34
- const HostAppControlPressInputSchema = z.object({
35
- tool: z.literal("press"),
36
- app: z.string(),
37
- /** Single key identifier, e.g. "return", "a", "f12". */
38
- key: z.string(),
39
- /** Modifier list, e.g. ["cmd", "shift"]. */
40
- modifiers: z.array(z.string()).optional(),
41
- /** Hold duration in milliseconds. */
42
- duration_ms: z.number().optional(),
43
- });
44
-
45
- const HostAppControlComboInputSchema = z.object({
46
- tool: z.literal("combo"),
47
- app: z.string(),
48
- /** Sequence of keys pressed simultaneously, e.g. ["cmd", "shift", "4"]. */
49
- keys: z.array(z.string()),
50
- /** Hold duration in milliseconds. */
51
- duration_ms: z.number().optional(),
52
- });
53
-
54
- /** A single step inside a sequence: one key press with optional modifiers, hold duration, and post-press gap. */
55
- export const HostAppControlSequenceStepSchema = z.object({
56
- /** Single key identifier, e.g. "right", "a", "return". */
57
- key: z.string(),
58
- /** Modifier list, e.g. ["cmd", "shift"]. Omit for no modifiers. */
59
- modifiers: z.array(z.string()).optional(),
60
- /** Hold duration for this key in milliseconds. */
61
- duration_ms: z.number().optional(),
62
- /** Pause after this step before starting the next, in milliseconds. */
63
- gap_ms: z.number().optional(),
64
- });
65
-
66
- export type HostAppControlSequenceStep = z.infer<
67
- typeof HostAppControlSequenceStepSchema
68
- >;
69
-
70
- const HostAppControlSequenceInputSchema = z.object({
71
- tool: z.literal("sequence"),
72
- app: z.string(),
73
- /** Ordered list of single-key presses to execute serially. */
74
- steps: z.array(HostAppControlSequenceStepSchema),
75
- });
76
-
77
- const HostAppControlTypeInputSchema = z.object({
78
- tool: z.literal("type"),
79
- app: z.string(),
80
- text: z.string(),
81
- });
82
-
83
- const HostAppControlClickInputSchema = z.object({
84
- tool: z.literal("click"),
85
- app: z.string(),
86
- x: z.number(),
87
- y: z.number(),
88
- button: z.enum(["left", "right", "middle"]).optional(),
89
- double: z.boolean().optional(),
90
- });
91
-
92
- const HostAppControlDragInputSchema = z.object({
93
- tool: z.literal("drag"),
94
- app: z.string(),
95
- from_x: z.number(),
96
- from_y: z.number(),
97
- to_x: z.number(),
98
- to_y: z.number(),
99
- button: z.enum(["left", "right", "middle"]).optional(),
100
- });
101
-
102
- const HostAppControlStopInputSchema = z.object({
103
- tool: z.literal("stop"),
104
- /** Optional — when omitted the proxy stops whichever app currently holds the session. */
105
- app: z.string().optional(),
106
- /** Free-form reason, surfaced for logging. */
107
- reason: z.string().optional(),
108
- });
109
-
110
- /** Inputs accepted by the nine app-control tool variants. */
111
- export const HostAppControlInputSchema = z.discriminatedUnion("tool", [
112
- HostAppControlStartInputSchema,
113
- HostAppControlObserveInputSchema,
114
- HostAppControlPressInputSchema,
115
- HostAppControlComboInputSchema,
116
- HostAppControlSequenceInputSchema,
117
- HostAppControlTypeInputSchema,
118
- HostAppControlClickInputSchema,
119
- HostAppControlDragInputSchema,
120
- HostAppControlStopInputSchema,
121
- ]);
122
-
123
- export type HostAppControlInput = z.infer<typeof HostAppControlInputSchema>;
124
-
125
- export const HostAppControlRequestEventSchema = z.object({
126
- type: z.literal("host_app_control_request"),
127
- requestId: z.string(),
128
- conversationId: z.string(),
129
- /** "app_control_start", "app_control_observe", etc. */
130
- toolName: z.string(),
131
- input: HostAppControlInputSchema,
132
- });
133
-
134
- export type HostAppControlRequestEvent = z.infer<
135
- typeof HostAppControlRequestEventSchema
136
- >;
137
-
138
- export const HostAppControlCancelEventSchema = z.object({
139
- type: z.literal("host_app_control_cancel"),
140
- requestId: z.string(),
141
- conversationId: z.string(),
142
- });
143
-
144
- export type HostAppControlCancelEvent = z.infer<
145
- typeof HostAppControlCancelEventSchema
146
- >;