@fabric-harness/azure 0.5.0 → 0.6.1

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/README.md CHANGED
@@ -9,11 +9,42 @@ Current surface:
9
9
  - `createAzureKeyVaultSecretResolver()` — Key Vault secret resolver for scoped commands.
10
10
  - `FoundryAgentServiceClient` / `foundryAgentTool()` — invoke Azure AI Foundry Agent Service from Fabric agents.
11
11
  - `AzureArmClient` tools for Container Apps jobs, AKS Run Command, and ACI exec-session creation.
12
+ - **`aksSandbox()`** (subpath: `@fabric-harness/azure/aks-sandbox`) — full `SandboxEnv` runtime backed by an AKS pod. Pulls cluster credentials via ARM `listClusterUserCredential` and delegates to `kubernetesSandbox` from `@fabric-harness/connectors/k8s`.
12
13
 
13
14
  ## Install
14
15
 
15
16
  ```sh
16
17
  npm install @fabric-harness/azure @fabric-harness/sdk
18
+
19
+ # Optional: required only when using aksSandbox
20
+ npm install @kubernetes/client-node
21
+ ```
22
+
23
+ ## AKS sandbox (full SandboxEnv)
24
+
25
+ Run an entire agent inside an AKS pod — `exec`/`readFile`/`writeFile`/`mkdir`/`rm` all work over the pod.
26
+
27
+ ```ts
28
+ import { init } from '@fabric-harness/sdk';
29
+ import { createAzureArmClient } from '@fabric-harness/azure';
30
+ import { aksSandbox } from '@fabric-harness/azure/aks-sandbox';
31
+
32
+ const arm = createAzureArmClient({
33
+ subscriptionId: process.env.AZURE_SUBSCRIPTION_ID!,
34
+ token: process.env.AZURE_ACCESS_TOKEN!,
35
+ });
36
+
37
+ const sandbox = await aksSandbox({
38
+ arm,
39
+ resourceGroup: 'my-rg',
40
+ clusterName: 'my-aks',
41
+ // Either attach to an existing pod:
42
+ podName: 'agent-pod',
43
+ // Or create an ephemeral pod from an image (auto-deleted on cleanup):
44
+ // image: 'alpine:latest',
45
+ });
46
+
47
+ const fabric = await init({ sandbox });
17
48
  ```
18
49
 
19
50
  ## Foundry Agent Service as a tool
@@ -39,6 +70,10 @@ const arm = createAzureArmClient({ subscriptionId: process.env.AZURE_SUBSCRIPTIO
39
70
  const tools = [azureContainerAppsJobTool(arm), azureAksRunCommandTool(arm)];
40
71
  ```
41
72
 
73
+ ## Build targets
74
+
75
+ `fh build --target aks` and `fh build --target aca` emit the deployment scaffolding for AKS (k8s manifests with health probes) and Azure Container Apps (azd project + Bicep with scale-to-zero) respectively. See [Azure deployment](https://harness.fabric.pro/docs/deployment/azure).
76
+
42
77
  Keep Azure credentials in environment variables, managed identity token providers, or secret stores. Do not put tokens in prompts or payloads.
43
78
 
44
79
  ## License
@@ -0,0 +1,35 @@
1
+ import type { SandboxEnv } from '@fabric-harness/sdk';
2
+ import type { AzureArmClient } from './index.js';
3
+ /**
4
+ * AKS-flavored Kubernetes sandbox. Pulls cluster credentials from the AKS
5
+ * `listClusterUserCredentials` endpoint, builds a `@kubernetes/client-node`
6
+ * `KubeConfig`, and delegates to `kubernetesSandbox`.
7
+ *
8
+ * Requires both peer deps:
9
+ * ```sh
10
+ * npm install @kubernetes/client-node
11
+ * ```
12
+ *
13
+ * Pod lifecycle: by default this attaches to an existing pod. To have the
14
+ * sandbox create its own ephemeral pod from an image, supply `image` and the
15
+ * pod will be created on first use and deleted on `cleanup()`.
16
+ */
17
+ export interface AksSandboxOptions {
18
+ arm: AzureArmClient;
19
+ resourceGroup: string;
20
+ clusterName: string;
21
+ /** Kubernetes namespace. Defaults to `default`. */
22
+ namespace?: string;
23
+ /** Existing pod name to attach to. Mutually exclusive with `image`. */
24
+ podName?: string;
25
+ /** Container image. If set, AKS sandbox creates an ephemeral pod and deletes it on cleanup. */
26
+ image?: string;
27
+ /** Container name inside the pod. */
28
+ container?: string;
29
+ /** AKS API version. */
30
+ apiVersion?: string;
31
+ /** Working directory inside the pod. Defaults to `/workspace`. */
32
+ cwd?: string;
33
+ }
34
+ export declare function aksSandbox(options: AksSandboxOptions): Promise<SandboxEnv>;
35
+ //# sourceMappingURL=aks-sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aks-sandbox.d.ts","sourceRoot":"","sources":["../src/aks-sandbox.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAIjD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,iBAAiB;IAChC,GAAG,EAAE,cAAc,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+FAA+F;IAC/F,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uBAAuB;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAsDhF"}
@@ -0,0 +1,64 @@
1
+ import { createRequire } from 'node:module';
2
+ import { kubernetesSandbox, createKubernetesPod } from '@fabric-harness/connectors/k8s';
3
+ const requireFromHere = createRequire(import.meta.url);
4
+ export async function aksSandbox(options) {
5
+ if (!options.podName && !options.image) {
6
+ throw new Error('aksSandbox: provide either `podName` (attach) or `image` (ephemeral pod).');
7
+ }
8
+ const namespace = options.namespace ?? 'default';
9
+ const apiVersion = options.apiVersion ?? '2024-02-01';
10
+ const credResponse = await options.arm.request('POST', options.arm.resourcePath(options.resourceGroup, `Microsoft.ContainerService/managedClusters/${encodeURIComponent(options.clusterName)}/listClusterUserCredential`), undefined, { 'api-version': apiVersion });
11
+ const encoded = credResponse.kubeconfigs?.[0]?.value;
12
+ if (!encoded)
13
+ throw new Error(`aksSandbox: no kubeconfig returned for ${options.resourceGroup}/${options.clusterName}`);
14
+ const kubeconfig = Buffer.from(encoded, 'base64').toString('utf8');
15
+ const { KubeConfig, CoreV1Api } = loadK8sModule();
16
+ const kc = new KubeConfig();
17
+ kc.loadFromString(kubeconfig);
18
+ let podName = options.podName;
19
+ let ownsPod = false;
20
+ if (!podName) {
21
+ podName = `fabric-harness-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
22
+ const core = kc.makeApiClient(CoreV1Api);
23
+ await core.createNamespacedPod(namespace, {
24
+ apiVersion: 'v1',
25
+ kind: 'Pod',
26
+ metadata: { name: podName, labels: { 'app.kubernetes.io/managed-by': 'fabric-harness' } },
27
+ spec: {
28
+ restartPolicy: 'Never',
29
+ containers: [{
30
+ name: options.container ?? 'main',
31
+ image: options.image,
32
+ command: ['sh', '-c', 'mkdir -p /workspace && sleep infinity'],
33
+ workingDir: options.cwd ?? '/workspace',
34
+ }],
35
+ },
36
+ });
37
+ ownsPod = true;
38
+ }
39
+ const pod = createKubernetesPod({
40
+ kubeConfig: kc,
41
+ namespace,
42
+ podName,
43
+ ...(options.container ? { container: options.container } : {}),
44
+ ownsPod,
45
+ });
46
+ return kubernetesSandbox(pod, {
47
+ cwd: options.cwd ?? '/workspace',
48
+ cleanup: ownsPod,
49
+ });
50
+ }
51
+ let cachedK8sModule;
52
+ function loadK8sModule() {
53
+ if (cachedK8sModule)
54
+ return cachedK8sModule;
55
+ try {
56
+ const mod = requireFromHere('@kubernetes/client-node');
57
+ cachedK8sModule = mod;
58
+ return mod;
59
+ }
60
+ catch {
61
+ throw new Error('aksSandbox requires the `@kubernetes/client-node` peer dependency. Install it with: npm install @kubernetes/client-node');
62
+ }
63
+ }
64
+ //# sourceMappingURL=aks-sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aks-sandbox.js","sourceRoot":"","sources":["../src/aks-sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAIxF,MAAM,eAAe,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAkCvD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAA0B;IACzD,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,2EAA2E,CAAC,CAAC;IAC/F,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,SAAS,CAAC;IACjD,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,YAAY,CAAC;IAEtD,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAC5C,MAAM,EACN,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,aAAa,EAAE,8CAA8C,kBAAkB,CAAC,OAAO,CAAC,WAAW,CAAC,4BAA4B,CAAC,EAClK,SAAS,EACT,EAAE,aAAa,EAAE,UAAU,EAAE,CAC9B,CAAC;IACF,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;IACrD,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,OAAO,CAAC,aAAa,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;IACxH,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEnE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,aAAa,EAAE,CAAC;IAClD,MAAM,EAAE,GAAG,IAAI,UAAU,EAAE,CAAC;IAC5B,EAAE,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;IAE9B,IAAI,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAC9B,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,GAAG,kBAAkB,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QAChG,MAAM,IAAI,GAAI,EAAkE,CAAC,aAAa,CAAC,SAAS,CAAgF,CAAC;QACzL,MAAM,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE;YACxC,UAAU,EAAE,IAAI;YAChB,IAAI,EAAE,KAAK;YACX,QAAQ,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,8BAA8B,EAAE,gBAAgB,EAAE,EAAE;YACzF,IAAI,EAAE;gBACJ,aAAa,EAAE,OAAO;gBACtB,UAAU,EAAE,CAAC;wBACX,IAAI,EAAE,OAAO,CAAC,SAAS,IAAI,MAAM;wBACjC,KAAK,EAAE,OAAO,CAAC,KAAK;wBACpB,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,uCAAuC,CAAC;wBAC9D,UAAU,EAAE,OAAO,CAAC,GAAG,IAAI,YAAY;qBACxC,CAAC;aACH;SACF,CAAC,CAAC;QACH,OAAO,GAAG,IAAI,CAAC;IACjB,CAAC;IAED,MAAM,GAAG,GAAG,mBAAmB,CAAC;QAC9B,UAAU,EAAE,EAAE;QACd,SAAS;QACT,OAAO;QACP,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9D,OAAO;KACR,CAAC,CAAC;IACH,OAAO,iBAAiB,CAAC,GAAG,EAAE;QAC5B,GAAG,EAAE,OAAO,CAAC,GAAG,IAAI,YAAY;QAChC,OAAO,EAAE,OAAO;KACjB,CAAC,CAAC;AACL,CAAC;AAMD,IAAI,eAAsC,CAAC;AAE3C,SAAS,aAAa;IACpB,IAAI,eAAe;QAAE,OAAO,eAAe,CAAC;IAC5C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,eAAe,CAAC,yBAAyB,CAAc,CAAC;QACpE,eAAe,GAAG,GAAG,CAAC;QACtB,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,yHAAyH,CAAC,CAAC;IAC7I,CAAC;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fabric-harness/azure",
3
- "version": "0.5.0",
3
+ "version": "0.6.1",
4
4
  "description": "Azure Container Apps / Container Instances / AKS adapter for Fabric Harness.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Fabric",
@@ -32,15 +32,35 @@
32
32
  },
33
33
  "main": "dist/index.js",
34
34
  "types": "dist/index.d.ts",
35
+ "exports": {
36
+ ".": {
37
+ "types": "./dist/index.d.ts",
38
+ "import": "./dist/index.js"
39
+ },
40
+ "./aks-sandbox": {
41
+ "types": "./dist/aks-sandbox.d.ts",
42
+ "import": "./dist/aks-sandbox.js"
43
+ }
44
+ },
35
45
  "files": [
36
46
  "dist",
37
47
  "README.md",
38
48
  "LICENSE"
39
49
  ],
40
50
  "dependencies": {
41
- "@fabric-harness/sdk": "0.5.0"
51
+ "@fabric-harness/connectors": "0.6.1",
52
+ "@fabric-harness/sdk": "0.6.1"
53
+ },
54
+ "peerDependencies": {
55
+ "@kubernetes/client-node": "^0.21.0"
56
+ },
57
+ "peerDependenciesMeta": {
58
+ "@kubernetes/client-node": {
59
+ "optional": true
60
+ }
42
61
  },
43
62
  "devDependencies": {
63
+ "@kubernetes/client-node": "^0.21.0",
44
64
  "@types/node": "^22.15.3",
45
65
  "typescript": "^5.8.3",
46
66
  "vitest": "^4.1.5"