@huaweidevtools/aishell-dsh-e2b 0.0.1-beta.3 → 0.0.1-beta.5

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/lib/index.js CHANGED
@@ -907,6 +907,18 @@ defineMethod("transform", [
907
907
  * used against should reach it.
908
908
  */
909
909
  const MAX_LIST_PAGES = 10;
910
+ /**
911
+ * The template to start from when the caller names none.
912
+ *
913
+ * Not the SDK's own default. The SDK resolves an omitted template to `"base"`,
914
+ * a name from the hosted service; this gateway's templates are its own, and it
915
+ * answers `"base"` with `404 sandbox unknown was not found` — a message that
916
+ * reads like a missing sandbox rather than an unknown template, which is what
917
+ * makes it worth pinning here rather than discovering at the first create.
918
+ *
919
+ * `"default"` is what this gateway provisions.
920
+ */
921
+ const DEFAULT_TEMPLATE = "default";
910
922
  /** Builds and caches SDK handles, one per sandbox id. */
911
923
  var SandboxClient = class {
912
924
  constructor(options) {
@@ -929,7 +941,8 @@ var SandboxClient = class {
929
941
  /**
930
942
  * Create a sandbox and cache its handle.
931
943
  *
932
- * @param template - the template name or id; the SDK's own default when omitted.
944
+ * @param template - the template name or id; {@link DEFAULT_TEMPLATE} when
945
+ * omitted.
933
946
  * @param options - create options forwarded to the SDK.
934
947
  * @returns the created sandbox handle.
935
948
  */
@@ -941,11 +954,8 @@ var SandboxClient = class {
941
954
  ...options.envs === void 0 ? {} : { envs: options.envs },
942
955
  ...options.metadata === void 0 ? {} : { metadata: options.metadata }
943
956
  };
944
- const sandbox = await this.runWithKeyRefresh(options.signal, (apiKey, signal) => template === void 0 ? Sandbox.create({
945
- ...common,
946
- apiKey,
947
- ...signal === void 0 ? {} : { signal }
948
- }) : Sandbox.create(template, {
957
+ const resolved = template ?? DEFAULT_TEMPLATE;
958
+ const sandbox = await this.runWithKeyRefresh(options.signal, (apiKey, signal) => Sandbox.create(resolved, {
949
959
  ...common,
950
960
  apiKey,
951
961
  ...signal === void 0 ? {} : { signal }
@@ -2429,55 +2439,19 @@ function getPortUrlTool(deps) {
2429
2439
  }
2430
2440
 
2431
2441
  //#endregion
2432
- //#region src/index.ts
2433
- /** The provisioning service the API key is fetched from. */
2434
- const DEFAULT_API_BASE_URL = "https://openapi.aishell.openbuildlab.com";
2435
- /** The sandbox gateway's domain — the value an E2B client calls `E2B_DOMAIN`. */
2436
- const DEFAULT_DOMAIN = "aishell.openbuildlab.com";
2437
- /** Default per-request timeout for both the key fetch and SDK calls. */
2438
- const DEFAULT_REQUEST_TIMEOUT_MS = 6e4;
2439
- /** Position of the tier guidance in the assembled prompt. */
2442
+ //#region src/prompt.ts
2443
+ /** Position of the tier guidance in the assembled context. */
2440
2444
  const SANDBOX_PROMPT_ORDER = 110;
2441
2445
  /** Name this contribution registers under; unique across the assembled prompt. */
2442
2446
  const SANDBOX_SECTION_NAME = "aishell:e2b";
2443
- /**
2444
- * What the model reads about which tier to use.
2445
- *
2446
- * This is the plugin's reason for existing. Without it the model has a set of
2447
- * sandbox tools and no basis for preferring them over provisioning real
2448
- * resources — or for preferring those over a sandbox.
2449
- *
2450
- * ## Why the split is stated by use and by scale
2451
- *
2452
- * An earlier version drew the line at lifecycle: "does the result need to
2453
- * outlive the task?" That is the property that actually decides the tier, but
2454
- * it is one the model has to *infer* about work that has not been described in
2455
- * those terms yet. "A web page or a small demo" versus "a production system" is
2456
- * a distinction the user can answer directly, and it maps onto the lifecycle
2457
- * question without asking the model to guess at it.
2458
- *
2459
- * ## Why it says to ask
2460
- *
2461
- * A tie-break the model performs silently is a decision the user never sees
2462
- * until the bill or the outage. When the request does not make the tier
2463
- * obvious, the model asks — and says what the choice costs, because "sandbox vs
2464
- * Terraform" means nothing to someone who has not met either.
2465
- *
2466
- * The distinction is stated in consequences, not mechanism: throwaway and free
2467
- * to discard, versus real resources that bill and are meant to keep running.
2468
- *
2469
- * ## What it does not say
2470
- *
2471
- * It does not describe the Terraform workflow. That belongs to the plugin that
2472
- * owns those tools, which also states the approvals each step needs — and the
2473
- * two sections land far apart in the assembled prompt, so repeating it here
2474
- * would risk two instructions drifting out of step.
2475
- */
2476
- const SANDBOX_GUIDANCE = `A sandbox is a disposable Linux environment: it runs for a bounded time, then is deleted along with everything in it.
2447
+ /** What the model reads about which tier to use. */
2448
+ const SANDBOX_GUIDANCE = `A sandbox is a Linux environment running remotely. It exists for a bounded time, then is deleted along with everything in it. What it gives you that this machine does not is a public address.
2477
2449
 
2478
- Use the sandbox tools (aishell__sandbox_*) when the ask is a web page or a simple demo-scale web app — something to look at, or to try out, that does not need to keep existing.
2450
+ That is the clearest signal: when the work has to be deployed somewhere reachable and the user wants a URL they can open — a web app, a demo, a service, a static page — use the sandbox tools (aishell__sandbox_*). Put the files there with aishell__sandbox_files_write, start the server with aishell__sandbox_commands_run and background: true, then call aishell__sandbox_get_port_url and give the user that address.
2479
2451
 
2480
- Deploy a production system instead, with the Terraform tools (aishell__terraform_* and their neighbours), when the result is real infrastructure: it will cost money, it should keep running, and it will be operated.
2452
+ At the other end, a production system belongs in real infrastructure, deployed with the Terraform tools (aishell__terraform_* and their neighbours). It will cost money, it should keep running, and it will be operated. The sandbox is the wrong tier for it not because it is small but because it is deliberately short-lived — the address stops working when it expires.
2453
+
2454
+ So: a page or a demo, or anything that should end in a URL to open, is a sandbox. A system to run and keep running is Terraform.
2481
2455
 
2482
2456
  If the request does not make clear which of these it is, ask the user before choosing. Say what the difference amounts to for them: a sandbox is throwaway and costs nothing to discard, while Terraform provisions real resources that are billed and meant to keep running. Follow what they pick.
2483
2457
 
@@ -2485,6 +2459,34 @@ A sandbox is often the right place to work something out before committing real
2485
2459
 
2486
2460
  This conversation works in at most one sandbox at a time. Create it with aishell__sandbox_create before the tools that use it, and choose its lifetime there — the value should match what the work needs, since the sandbox and its contents are deleted when it expires.`;
2487
2461
  /**
2462
+ * Register the guidance section.
2463
+ *
2464
+ * Deferred behind `ctx.inject` rather than declared in this plugin's own
2465
+ * `inject`: the guidance is an enhancement, and a deployment without a system
2466
+ * prompt should lose it rather than fail to mount.
2467
+ *
2468
+ * @param ctx - host context.
2469
+ */
2470
+ function registerSandboxGuidance(ctx) {
2471
+ ctx.inject(["systemPrompt"], (scope) => {
2472
+ scope.systemPrompt.section({
2473
+ name: SANDBOX_SECTION_NAME,
2474
+ order: SANDBOX_PROMPT_ORDER,
2475
+ interpolate: false,
2476
+ text: ({ scope: renderScope }) => ctx.tools.get("aishell__sandbox_create", renderScope) === void 0 ? "" : SANDBOX_GUIDANCE
2477
+ });
2478
+ });
2479
+ }
2480
+
2481
+ //#endregion
2482
+ //#region src/index.ts
2483
+ /** The provisioning service the API key is fetched from. */
2484
+ const DEFAULT_API_BASE_URL = "https://openapi.aishell.openbuildlab.com";
2485
+ /** The sandbox gateway's domain — the value an E2B client calls `E2B_DOMAIN`. */
2486
+ const DEFAULT_DOMAIN = "aishell.openbuildlab.com";
2487
+ /** Default per-request timeout for both the key fetch and SDK calls. */
2488
+ const DEFAULT_REQUEST_TIMEOUT_MS = 6e4;
2489
+ /**
2488
2490
  * Settings schema for this entry.
2489
2491
  *
2490
2492
  * Both URLs are Volatile: they are deployment facts that differ between a
@@ -2535,14 +2537,7 @@ function apply(ctx, config) {
2535
2537
  ctx.effect(() => ctx.on("aishell/credentials-updated", () => {
2536
2538
  keys.invalidate();
2537
2539
  }), "aishell-e2b: credential changes");
2538
- ctx.inject(["systemPrompt"], (scope) => {
2539
- scope.systemPrompt.section({
2540
- name: SANDBOX_SECTION_NAME,
2541
- order: SANDBOX_PROMPT_ORDER,
2542
- interpolate: false,
2543
- text: ({ scope: scope$1 }) => ctx.tools.get("aishell__sandbox_create", scope$1) === void 0 ? "" : SANDBOX_GUIDANCE
2544
- });
2545
- });
2540
+ registerSandboxGuidance(ctx);
2546
2541
  }
2547
2542
 
2548
2543
  //#endregion
@@ -20,6 +20,18 @@
20
20
  */
21
21
  import { Sandbox } from 'e2b';
22
22
  import type { SandboxKeySource } from './sandbox-key.ts';
23
+ /**
24
+ * The template to start from when the caller names none.
25
+ *
26
+ * Not the SDK's own default. The SDK resolves an omitted template to `"base"`,
27
+ * a name from the hosted service; this gateway's templates are its own, and it
28
+ * answers `"base"` with `404 sandbox unknown was not found` — a message that
29
+ * reads like a missing sandbox rather than an unknown template, which is what
30
+ * makes it worth pinning here rather than discovering at the first create.
31
+ *
32
+ * `"default"` is what this gateway provisions.
33
+ */
34
+ export declare const DEFAULT_TEMPLATE = "default";
23
35
  /** How the connection is parameterised; every field is read per call. */
24
36
  export interface SandboxClientOptions {
25
37
  /** The gateway's domain, e.g. `aishell.openbuildlab.com`. */
@@ -45,7 +57,8 @@ export declare class SandboxClient {
45
57
  /**
46
58
  * Create a sandbox and cache its handle.
47
59
  *
48
- * @param template - the template name or id; the SDK's own default when omitted.
60
+ * @param template - the template name or id; {@link DEFAULT_TEMPLATE} when
61
+ * omitted.
49
62
  * @param options - create options forwarded to the SDK.
50
63
  * @returns the created sandbox handle.
51
64
  */
@@ -34,44 +34,6 @@
34
34
  */
35
35
  import type { Context, Volatile } from '@deepseek-ai/cordis';
36
36
  import z from '@deepseek-ai/schemastery';
37
- /** Position of the tier guidance in the assembled prompt. */
38
- export declare const SANDBOX_PROMPT_ORDER = 110;
39
- /** Name this contribution registers under; unique across the assembled prompt. */
40
- export declare const SANDBOX_SECTION_NAME = "aishell:e2b";
41
- /**
42
- * What the model reads about which tier to use.
43
- *
44
- * This is the plugin's reason for existing. Without it the model has a set of
45
- * sandbox tools and no basis for preferring them over provisioning real
46
- * resources — or for preferring those over a sandbox.
47
- *
48
- * ## Why the split is stated by use and by scale
49
- *
50
- * An earlier version drew the line at lifecycle: "does the result need to
51
- * outlive the task?" That is the property that actually decides the tier, but
52
- * it is one the model has to *infer* about work that has not been described in
53
- * those terms yet. "A web page or a small demo" versus "a production system" is
54
- * a distinction the user can answer directly, and it maps onto the lifecycle
55
- * question without asking the model to guess at it.
56
- *
57
- * ## Why it says to ask
58
- *
59
- * A tie-break the model performs silently is a decision the user never sees
60
- * until the bill or the outage. When the request does not make the tier
61
- * obvious, the model asks — and says what the choice costs, because "sandbox vs
62
- * Terraform" means nothing to someone who has not met either.
63
- *
64
- * The distinction is stated in consequences, not mechanism: throwaway and free
65
- * to discard, versus real resources that bill and are meant to keep running.
66
- *
67
- * ## What it does not say
68
- *
69
- * It does not describe the Terraform workflow. That belongs to the plugin that
70
- * owns those tools, which also states the approvals each step needs — and the
71
- * two sections land far apart in the assembled prompt, so repeating it here
72
- * would risk two instructions drifting out of step.
73
- */
74
- export declare const SANDBOX_GUIDANCE = "A sandbox is a disposable Linux environment: it runs for a bounded time, then is deleted along with everything in it.\n\nUse the sandbox tools (aishell__sandbox_*) when the ask is a web page or a simple demo-scale web app \u2014 something to look at, or to try out, that does not need to keep existing.\n\nDeploy a production system instead, with the Terraform tools (aishell__terraform_* and their neighbours), when the result is real infrastructure: it will cost money, it should keep running, and it will be operated.\n\nIf the request does not make clear which of these it is, ask the user before choosing. Say what the difference amounts to for them: a sandbox is throwaway and costs nothing to discard, while Terraform provisions real resources that are billed and meant to keep running. Follow what they pick.\n\nA sandbox is often the right place to work something out before committing real resources to it.\n\nThis conversation works in at most one sandbox at a time. Create it with aishell__sandbox_create before the tools that use it, and choose its lifetime there \u2014 the value should match what the work needs, since the sandbox and its contents are deleted when it expires.";
75
37
  /** Plugin config. */
76
38
  export interface Config {
77
39
  /** Base URL of the sandbox key provisioning service. */
@@ -97,6 +59,7 @@ export declare const Config: z<Schemastery.ObjectS<NoInfer<{
97
59
  domain: z<string, string, "volatile-defined">;
98
60
  requestTimeoutMs: z<number, number, "volatile-defined">;
99
61
  }>>, "plain">;
62
+ export { SANDBOX_GUIDANCE, SANDBOX_PROMPT_ORDER, SANDBOX_SECTION_NAME } from './prompt.ts';
100
63
  export declare const name = "aishell-e2b";
101
64
  /**
102
65
  * Required services: the tool registry alone.
@@ -0,0 +1,62 @@
1
+ /**
2
+ * What the model reads about which tier to use.
3
+ *
4
+ * ## Why this is its own module
5
+ *
6
+ * The text and the mechanism that delivers it belong together. Split across
7
+ * `index.ts` — the string one place, the `systemPrompt.section()` call another —
8
+ * the only way to see what the model actually reads is to read both. Here they
9
+ * sit side by side, and `apply()` just calls {@link registerSandboxGuidance}.
10
+ *
11
+ * ## Why the split is stated three ways
12
+ *
13
+ * An earlier version drew the line at lifecycle alone: "does the result need to
14
+ * outlive the task?" That is the property that actually decides the tier, but it
15
+ * is one the model has to *infer* about work that has not been described in
16
+ * those terms yet.
17
+ *
18
+ * Two things make it answerable instead:
19
+ *
20
+ * - **What the user asked for.** "A web page or a demo" versus "a production
21
+ * system" is a distinction a person can answer directly.
22
+ * - **What the work needs.** The one capability a sandbox has that this
23
+ * machine does not is a public address. A request to deploy something and
24
+ * get a URL back is the strongest signal there is, and it is stated first
25
+ * because it is the least ambiguous.
26
+ *
27
+ * The three are kept together rather than reduced to one. They disagree at the
28
+ * edges — a demo that must stay up, a production service that starts as a
29
+ * sketch — and when they do, asking the user is the answer, which the text says.
30
+ *
31
+ * ## Why it says to ask
32
+ *
33
+ * A tie-break the model performs silently is a decision the user never sees
34
+ * until the bill or the outage. So when the request does not make the tier
35
+ * obvious, the model asks — and says what the choice costs, because "sandbox vs
36
+ * Terraform" means nothing to someone who has not met either.
37
+ *
38
+ * ## What it does not say
39
+ *
40
+ * It does not describe the Terraform workflow. That belongs to the plugin that
41
+ * owns those tools, which also states the approvals each step needs.
42
+ *
43
+ * @module @huaweidevtools/aishell-dsh-e2b/prompt
44
+ */
45
+ import type { Context } from '@deepseek-ai/cordis';
46
+ /** Position of the tier guidance in the assembled context. */
47
+ export declare const SANDBOX_PROMPT_ORDER = 110;
48
+ /** Name this contribution registers under; unique across the assembled prompt. */
49
+ export declare const SANDBOX_SECTION_NAME = "aishell:e2b";
50
+ /** What the model reads about which tier to use. */
51
+ export declare const SANDBOX_GUIDANCE = "A sandbox is a Linux environment running remotely. It exists for a bounded time, then is deleted along with everything in it. What it gives you that this machine does not is a public address.\n\nThat is the clearest signal: when the work has to be deployed somewhere reachable and the user wants a URL they can open \u2014 a web app, a demo, a service, a static page \u2014 use the sandbox tools (aishell__sandbox_*). Put the files there with aishell__sandbox_files_write, start the server with aishell__sandbox_commands_run and background: true, then call aishell__sandbox_get_port_url and give the user that address.\n\nAt the other end, a production system belongs in real infrastructure, deployed with the Terraform tools (aishell__terraform_* and their neighbours). It will cost money, it should keep running, and it will be operated. The sandbox is the wrong tier for it not because it is small but because it is deliberately short-lived \u2014 the address stops working when it expires.\n\nSo: a page or a demo, or anything that should end in a URL to open, is a sandbox. A system to run and keep running is Terraform.\n\nIf the request does not make clear which of these it is, ask the user before choosing. Say what the difference amounts to for them: a sandbox is throwaway and costs nothing to discard, while Terraform provisions real resources that are billed and meant to keep running. Follow what they pick.\n\nA sandbox is often the right place to work something out before committing real resources to it.\n\nThis conversation works in at most one sandbox at a time. Create it with aishell__sandbox_create before the tools that use it, and choose its lifetime there \u2014 the value should match what the work needs, since the sandbox and its contents are deleted when it expires.";
52
+ /**
53
+ * Register the guidance section.
54
+ *
55
+ * Deferred behind `ctx.inject` rather than declared in this plugin's own
56
+ * `inject`: the guidance is an enhancement, and a deployment without a system
57
+ * prompt should lose it rather than fail to mount.
58
+ *
59
+ * @param ctx - host context.
60
+ */
61
+ export declare function registerSandboxGuidance(ctx: Context): void;
62
+ //# sourceMappingURL=prompt.d.ts.map
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@huaweidevtools/aishell-dsh-e2b",
3
3
  "description": "Runs throwaway and preview deployments in E2B sandboxes on DSH — sandbox lifecycle, commands, and files as tools",
4
- "version": "0.0.1-beta.3",
4
+ "version": "0.0.1-beta.5",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -27,7 +27,7 @@
27
27
  "license": "Apache-2.0",
28
28
  "dependencies": {
29
29
  "e2b": "2.59.0",
30
- "@huaweidevtools/aishell-dsh-credentials-store": "0.0.1-beta.3"
30
+ "@huaweidevtools/aishell-dsh-credentials-store": "0.0.1-beta.5"
31
31
  },
32
32
  "peerDependencies": {
33
33
  "@deepseek-ai/cordis": "^4.0.4",