@ingram-tech/pulumi-ingram-cloud 0.1.0 → 0.2.0
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 +22 -22
- package/dist/connection.d.ts +1 -1
- package/dist/connection.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/resources.d.ts +12 -12
- package/dist/resources.js +36 -36
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
# @ingram-tech/pulumi-ingram-cloud
|
|
2
2
|
|
|
3
3
|
Pulumi dynamic resources for the [Ingram Cloud](https://cloud.ingram.tech) `/v1`
|
|
4
|
-
API. Declare your tenant's IC configuration —
|
|
4
|
+
API. Declare your tenant's IC configuration — agents, MCP servers, channels,
|
|
5
5
|
webhooks, BYOK model keys — as Pulumi resources instead of imperative
|
|
6
|
-
`register-*.ts` / `ensure-
|
|
6
|
+
`register-*.ts` / `ensure-agent.ts` scripts, so it lives in state and a change
|
|
7
7
|
is a `pulumi up`.
|
|
8
8
|
|
|
9
9
|
The library is published from the `pulumi/` folder of the
|
|
@@ -21,10 +21,10 @@ bun add @ingram-tech/pulumi-ingram-cloud @pulumi/pulumi
|
|
|
21
21
|
|
|
22
22
|
```
|
|
23
23
|
cloud.ingram.tech/pulumi/ THIS LIBRARY — knows nothing about any consumer
|
|
24
|
-
(
|
|
24
|
+
(Agent, McpServer, TelegramBot, WhatsAppConfig,
|
|
25
25
|
Webhook, ModelKey, Secret)
|
|
26
26
|
|
|
27
|
-
app repos (thornhill, …) declare their
|
|
27
|
+
app repos (thornhill, …) declare their AGENTS — the `instructions` are
|
|
28
28
|
app-owned content (prompts), so they stay in the app
|
|
29
29
|
repo, sourced from the app's own spec module. The app's
|
|
30
30
|
Pulumi program imports this library + those specs.
|
|
@@ -32,7 +32,7 @@ app repos (thornhill, …) declare their BLUEPRINTS — the `instructions` ar
|
|
|
32
32
|
infra repo (~/src/infra) declares tenant CHANNEL config (MCP, Telegram, WhatsApp,
|
|
33
33
|
webhook, model keys) alongside DNS/DB/Vercel, and can
|
|
34
34
|
read an app stack's outputs via pulumi.StackReference to
|
|
35
|
-
push IC-derived values (
|
|
35
|
+
push IC-derived values (agent ids, webhook secret)
|
|
36
36
|
into Vercel env. No prompts ever live here.
|
|
37
37
|
```
|
|
38
38
|
|
|
@@ -59,31 +59,31 @@ pulumi config set --secret ingram-cloud:token tha_live_…
|
|
|
59
59
|
|
|
60
60
|
## Resources
|
|
61
61
|
|
|
62
|
-
###
|
|
62
|
+
### IcAgent (declare in the APP repo)
|
|
63
63
|
|
|
64
64
|
Create-or-adopt by name → publish a new immutable version **only when the content
|
|
65
|
-
changed** → roll it out. Mirrors the old `ensure-
|
|
66
|
-
first `pulumi up` after switching from a script **adopts** the existing
|
|
65
|
+
changed** → roll it out. Mirrors the old `ensure-agent.ts` idempotency, so the
|
|
66
|
+
first `pulumi up` after switching from a script **adopts** the existing agent
|
|
67
67
|
(matched by name) rather than recreating it.
|
|
68
68
|
|
|
69
69
|
```ts
|
|
70
|
-
import {
|
|
70
|
+
import { AGENT_SPECS } from "../src/lib/cloud/agent-spec"; // app-owned
|
|
71
71
|
|
|
72
|
-
const curator = new ic.
|
|
72
|
+
const curator = new ic.IcAgent("curator", {
|
|
73
73
|
...conn,
|
|
74
|
-
name:
|
|
75
|
-
instructions:
|
|
76
|
-
model:
|
|
77
|
-
autoMemory:
|
|
74
|
+
name: AGENT_SPECS.curator.name,
|
|
75
|
+
instructions: AGENT_SPECS.curator.instructions,
|
|
76
|
+
model: AGENT_SPECS.curator.model,
|
|
77
|
+
autoMemory: AGENT_SPECS.curator.auto_memory,
|
|
78
78
|
// variables: [...], enabledHostedTools: [...], rolloutPercent: 100,
|
|
79
79
|
});
|
|
80
80
|
|
|
81
|
-
export const
|
|
81
|
+
export const curatorAgentId = curator.agentId;
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
> Attaching **existing**
|
|
85
|
-
> keep it as the app's migration script. New
|
|
86
|
-
> Pulumi does not own per-
|
|
84
|
+
> Attaching **existing** smiths to a agent is a one-time fleet backfill —
|
|
85
|
+
> keep it as the app's migration script. New smiths attach at birth in app code.
|
|
86
|
+
> Pulumi does not own per-smith runtime state.
|
|
87
87
|
|
|
88
88
|
### IcMcpServer, IcTelegramBot, IcWhatsAppConfig, IcWebhook, IcModelKey (declare in INFRA)
|
|
89
89
|
|
|
@@ -115,14 +115,14 @@ tenant runs an IC-hosted `app`.
|
|
|
115
115
|
|
|
116
116
|
## Importing resources a script already created
|
|
117
117
|
|
|
118
|
-
|
|
118
|
+
Agents and webhooks implement `read`, so you can adopt pre-existing ones:
|
|
119
119
|
|
|
120
120
|
```bash
|
|
121
|
-
pulumi import 'ingram-cloud:index:
|
|
121
|
+
pulumi import 'ingram-cloud:index:IcAgent' curator agt_123…
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
-
(
|
|
125
|
-
usually unnecessary — a plain `pulumi up` will reconcile the live
|
|
124
|
+
(Agents also self-adopt by name on first `create`, so an explicit import is
|
|
125
|
+
usually unnecessary — a plain `pulumi up` will reconcile the live agent.)
|
|
126
126
|
|
|
127
127
|
## Notes
|
|
128
128
|
|
package/dist/connection.d.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* program can spread it into every resource:
|
|
4
4
|
*
|
|
5
5
|
* const conn = connectionFromConfig();
|
|
6
|
-
* new ic.
|
|
6
|
+
* new ic.IcAgent("assistant", { ...conn, name: "…", instructions: "…" });
|
|
7
7
|
*
|
|
8
8
|
* Resolution order (first hit wins):
|
|
9
9
|
* baseUrl: `ingram-cloud:baseUrl` config → IC_BASE_URL → CLOUD_BASE_URL → prod
|
package/dist/connection.js
CHANGED
|
@@ -40,7 +40,7 @@ exports.connectionFromConfig = connectionFromConfig;
|
|
|
40
40
|
* program can spread it into every resource:
|
|
41
41
|
*
|
|
42
42
|
* const conn = connectionFromConfig();
|
|
43
|
-
* new ic.
|
|
43
|
+
* new ic.IcAgent("assistant", { ...conn, name: "…", instructions: "…" });
|
|
44
44
|
*
|
|
45
45
|
* Resolution order (first hit wins):
|
|
46
46
|
* baseUrl: `ingram-cloud:baseUrl` config → IC_BASE_URL → CLOUD_BASE_URL → prod
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* @ingram-tech/pulumi-ingram-cloud
|
|
3
3
|
*
|
|
4
4
|
* Pulumi dynamic resources for the Ingram Cloud /v1 API. See README.md for the
|
|
5
|
-
* repo-interaction model (library here,
|
|
5
|
+
* repo-interaction model (library here, agents declared in app repos,
|
|
6
6
|
* channel/tenant config in the infra repo).
|
|
7
7
|
*/
|
|
8
8
|
export * from "./resources";
|
package/dist/index.js
CHANGED
|
@@ -18,7 +18,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
18
18
|
* @ingram-tech/pulumi-ingram-cloud
|
|
19
19
|
*
|
|
20
20
|
* Pulumi dynamic resources for the Ingram Cloud /v1 API. See README.md for the
|
|
21
|
-
* repo-interaction model (library here,
|
|
21
|
+
* repo-interaction model (library here, agents declared in app repos,
|
|
22
22
|
* channel/tenant config in the infra repo).
|
|
23
23
|
*/
|
|
24
24
|
__exportStar(require("./resources"), exports);
|
package/dist/resources.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Ingram Cloud /v1 tenant configuration as Pulumi dynamic resources.
|
|
3
3
|
*
|
|
4
|
-
* Replaces the per-app `scripts/register-*.ts` / `ensure-
|
|
4
|
+
* Replaces the per-app `scripts/register-*.ts` / `ensure-agent.ts` one-shots
|
|
5
5
|
* with declarative resources, so IC wiring is a `pulumi up` and lives in state
|
|
6
6
|
* instead of drifting in someone's shell history.
|
|
7
7
|
*
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* additional secret output so it's encrypted in state.
|
|
11
11
|
*
|
|
12
12
|
* Where each resource is meant to be declared:
|
|
13
|
-
* - **
|
|
13
|
+
* - **Agents** (`IcAgent`) — the `instructions` are app-owned *content*,
|
|
14
14
|
* so declare these in the APP repo's Pulumi program, sourced from the app's
|
|
15
15
|
* own spec module. Never copy prompts into the infra repo.
|
|
16
16
|
* - **Channels / tenant config** (`IcMcpServer`, `IcTelegramBot`,
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
* Not modelled here, on purpose:
|
|
22
22
|
* - **Per-end-user actions** — creating users, binding channels, pushing
|
|
23
23
|
* per-user connection tokens, minting user tokens — happen at app runtime.
|
|
24
|
-
* - **Attaching existing
|
|
24
|
+
* - **Attaching existing smiths to an agent** — a one-time backfill that
|
|
25
25
|
* mutates the live fleet; keep it as the app's migration script. New
|
|
26
|
-
*
|
|
26
|
+
* smiths attach at birth in app code.
|
|
27
27
|
* - **Slack app factory** — config-token rotation is stateful and app-driven.
|
|
28
28
|
*/
|
|
29
29
|
import * as pulumi from "@pulumi/pulumi";
|
|
@@ -32,34 +32,34 @@ import * as pulumi from "@pulumi/pulumi";
|
|
|
32
32
|
* library version bump — consumers pin behaviour by pinning this package.
|
|
33
33
|
*/
|
|
34
34
|
export declare const IC_API_VERSION = "2026-05-01";
|
|
35
|
-
export interface
|
|
35
|
+
export interface AgentVariable {
|
|
36
36
|
name: string;
|
|
37
37
|
default?: string | null;
|
|
38
38
|
description?: string | null;
|
|
39
39
|
required?: boolean;
|
|
40
40
|
}
|
|
41
|
-
export interface
|
|
41
|
+
export interface IcAgentArgs {
|
|
42
42
|
baseUrl: pulumi.Input<string>;
|
|
43
43
|
token: pulumi.Input<string>;
|
|
44
|
-
/** Tenant-unique
|
|
44
|
+
/** Tenant-unique agent name (the create/adopt key). */
|
|
45
45
|
name: pulumi.Input<string>;
|
|
46
46
|
/** The persona/instruction template (may contain `{{ variables }}`). */
|
|
47
47
|
instructions?: pulumi.Input<string>;
|
|
48
48
|
model?: pulumi.Input<string>;
|
|
49
49
|
enabledHostedTools?: pulumi.Input<string[]>;
|
|
50
50
|
autoMemory?: pulumi.Input<boolean>;
|
|
51
|
-
variables?: pulumi.Input<
|
|
51
|
+
variables?: pulumi.Input<AgentVariable[]>;
|
|
52
52
|
/** Release note recorded when a new version is published. */
|
|
53
53
|
publishNote?: pulumi.Input<string>;
|
|
54
54
|
/** Rollout percentage for the published version (default 100). */
|
|
55
55
|
rolloutPercent?: pulumi.Input<number>;
|
|
56
56
|
}
|
|
57
|
-
export declare class
|
|
58
|
-
/** The `
|
|
59
|
-
readonly
|
|
57
|
+
export declare class IcAgent extends pulumi.dynamic.Resource {
|
|
58
|
+
/** The `agt_…` id (same as `.id`, exposed for convenience). */
|
|
59
|
+
readonly agentId: pulumi.Output<string>;
|
|
60
60
|
/** The version number currently rolled out. */
|
|
61
61
|
readonly activeVersion: pulumi.Output<number>;
|
|
62
|
-
constructor(name: string, args:
|
|
62
|
+
constructor(name: string, args: IcAgentArgs, opts?: pulumi.CustomResourceOptions);
|
|
63
63
|
}
|
|
64
64
|
export interface IcMcpServerArgs {
|
|
65
65
|
baseUrl: pulumi.Input<string>;
|
package/dist/resources.js
CHANGED
|
@@ -33,11 +33,11 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.IcSecret = exports.IcModelKey = exports.IcWebhook = exports.IcWhatsAppConfig = exports.IcTelegramBot = exports.IcMcpServer = exports.
|
|
36
|
+
exports.IcSecret = exports.IcModelKey = exports.IcWebhook = exports.IcWhatsAppConfig = exports.IcTelegramBot = exports.IcMcpServer = exports.IcAgent = exports.IC_API_VERSION = void 0;
|
|
37
37
|
/**
|
|
38
38
|
* Ingram Cloud /v1 tenant configuration as Pulumi dynamic resources.
|
|
39
39
|
*
|
|
40
|
-
* Replaces the per-app `scripts/register-*.ts` / `ensure-
|
|
40
|
+
* Replaces the per-app `scripts/register-*.ts` / `ensure-agent.ts` one-shots
|
|
41
41
|
* with declarative resources, so IC wiring is a `pulumi up` and lives in state
|
|
42
42
|
* instead of drifting in someone's shell history.
|
|
43
43
|
*
|
|
@@ -46,7 +46,7 @@ exports.IcSecret = exports.IcModelKey = exports.IcWebhook = exports.IcWhatsAppCo
|
|
|
46
46
|
* additional secret output so it's encrypted in state.
|
|
47
47
|
*
|
|
48
48
|
* Where each resource is meant to be declared:
|
|
49
|
-
* - **
|
|
49
|
+
* - **Agents** (`IcAgent`) — the `instructions` are app-owned *content*,
|
|
50
50
|
* so declare these in the APP repo's Pulumi program, sourced from the app's
|
|
51
51
|
* own spec module. Never copy prompts into the infra repo.
|
|
52
52
|
* - **Channels / tenant config** (`IcMcpServer`, `IcTelegramBot`,
|
|
@@ -57,9 +57,9 @@ exports.IcSecret = exports.IcModelKey = exports.IcWebhook = exports.IcWhatsAppCo
|
|
|
57
57
|
* Not modelled here, on purpose:
|
|
58
58
|
* - **Per-end-user actions** — creating users, binding channels, pushing
|
|
59
59
|
* per-user connection tokens, minting user tokens — happen at app runtime.
|
|
60
|
-
* - **Attaching existing
|
|
60
|
+
* - **Attaching existing smiths to an agent** — a one-time backfill that
|
|
61
61
|
* mutates the live fleet; keep it as the app's migration script. New
|
|
62
|
-
*
|
|
62
|
+
* smiths attach at birth in app code.
|
|
63
63
|
* - **Slack app factory** — config-token rotation is stateful and app-driven.
|
|
64
64
|
*/
|
|
65
65
|
const pulumi = __importStar(require("@pulumi/pulumi"));
|
|
@@ -91,7 +91,7 @@ async function icRequest(baseUrl, token, method, path, body, idempotencyKey) {
|
|
|
91
91
|
return text ? JSON.parse(text) : {};
|
|
92
92
|
}
|
|
93
93
|
// The draft body IC's create/patch expect (snake_case wire shape).
|
|
94
|
-
function
|
|
94
|
+
function agentBody(i) {
|
|
95
95
|
return {
|
|
96
96
|
name: i.name,
|
|
97
97
|
instructions: i.instructions ?? null,
|
|
@@ -103,7 +103,7 @@ function blueprintBody(i) {
|
|
|
103
103
|
}
|
|
104
104
|
// Stable signature of the *content* that warrants a new published version
|
|
105
105
|
// (name and rollout% deliberately excluded — a rename/restage is not new content).
|
|
106
|
-
function
|
|
106
|
+
function agentContentSig(i) {
|
|
107
107
|
return JSON.stringify({
|
|
108
108
|
instructions: i.instructions ?? null,
|
|
109
109
|
model: i.model ?? null,
|
|
@@ -112,8 +112,8 @@ function blueprintContentSig(i) {
|
|
|
112
112
|
variables: i.variables ?? [],
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
|
-
async function
|
|
116
|
-
const res = await icRequest(baseUrl, token, "GET", "/v1/
|
|
115
|
+
async function findAgentByName(baseUrl, token, name) {
|
|
116
|
+
const res = await icRequest(baseUrl, token, "GET", "/v1/agents");
|
|
117
117
|
return (res.data ?? []).find((b) => b.name === name) ?? null;
|
|
118
118
|
}
|
|
119
119
|
// Signature of the snapshot currently published as the active version, or null
|
|
@@ -121,12 +121,12 @@ async function findBlueprintByName(baseUrl, token, name) {
|
|
|
121
121
|
async function activeSnapshotSig(baseUrl, token, id, activeVersion) {
|
|
122
122
|
if (!activeVersion)
|
|
123
123
|
return null;
|
|
124
|
-
const res = await icRequest(baseUrl, token, "GET", `/v1/
|
|
124
|
+
const res = await icRequest(baseUrl, token, "GET", `/v1/agents/${id}/versions`);
|
|
125
125
|
const v = (res.data ?? []).find((x) => x.version === activeVersion);
|
|
126
126
|
if (!v)
|
|
127
127
|
return null;
|
|
128
128
|
const s = v.snapshot ?? {};
|
|
129
|
-
return
|
|
129
|
+
return agentContentSig({
|
|
130
130
|
instructions: s.instructions,
|
|
131
131
|
model: s.model,
|
|
132
132
|
enabledHostedTools: s.enabled_hosted_tools,
|
|
@@ -134,15 +134,15 @@ async function activeSnapshotSig(baseUrl, token, id, activeVersion) {
|
|
|
134
134
|
variables: s.variables,
|
|
135
135
|
});
|
|
136
136
|
}
|
|
137
|
-
// Ensure the live
|
|
137
|
+
// Ensure the live agent matches desired: adopt-or-create, publish iff the
|
|
138
138
|
// content drifted from the active version, then roll out at `percent`.
|
|
139
|
-
async function
|
|
139
|
+
async function reconcileAgent(i, knownId, priorSig) {
|
|
140
140
|
let id;
|
|
141
141
|
if (!knownId) {
|
|
142
|
-
const existing = await
|
|
142
|
+
const existing = await findAgentByName(i.baseUrl, i.token, i.name);
|
|
143
143
|
if (existing) {
|
|
144
144
|
id = existing.id;
|
|
145
|
-
await icRequest(i.baseUrl, i.token, "PATCH", `/v1/
|
|
145
|
+
await icRequest(i.baseUrl, i.token, "PATCH", `/v1/agents/${id}`, agentBody(i));
|
|
146
146
|
}
|
|
147
147
|
else {
|
|
148
148
|
// No idempotency key: Pulumi calls create once and tracks the id in
|
|
@@ -150,19 +150,19 @@ async function reconcileBlueprint(i, knownId, priorSig) {
|
|
|
150
150
|
// script→Pulumi migration. Keying on the name would replay a stale
|
|
151
151
|
// (possibly archived) create after a destroy+recreate within the 24h
|
|
152
152
|
// idempotency window.
|
|
153
|
-
const bp = await icRequest(i.baseUrl, i.token, "POST", "/v1/
|
|
153
|
+
const bp = await icRequest(i.baseUrl, i.token, "POST", "/v1/agents", agentBody(i));
|
|
154
154
|
id = bp.id;
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
else {
|
|
158
158
|
// Known id (update path): push the draft to the desired shape.
|
|
159
159
|
id = knownId;
|
|
160
|
-
await icRequest(i.baseUrl, i.token, "PATCH", `/v1/
|
|
160
|
+
await icRequest(i.baseUrl, i.token, "PATCH", `/v1/agents/${id}`, agentBody(i));
|
|
161
161
|
}
|
|
162
|
-
const bp = await icRequest(i.baseUrl, i.token, "GET", `/v1/
|
|
163
|
-
const desiredSig =
|
|
162
|
+
const bp = await icRequest(i.baseUrl, i.token, "GET", `/v1/agents/${id}`);
|
|
163
|
+
const desiredSig = agentContentSig(i);
|
|
164
164
|
// On the create path we don't know the prior sig — compare to what's actually
|
|
165
|
-
// published so adopting a script-made
|
|
165
|
+
// published so adopting a script-made agent doesn't churn a needless version.
|
|
166
166
|
const liveSig = priorSig ?? (await activeSnapshotSig(i.baseUrl, i.token, id, bp.active_version));
|
|
167
167
|
let version = bp.active_version ?? 0;
|
|
168
168
|
if (!bp.active_version || liveSig !== desiredSig) {
|
|
@@ -170,7 +170,7 @@ async function reconcileBlueprint(i, knownId, priorSig) {
|
|
|
170
170
|
// its number. Only the *first* publish auto-activates; later ones go live
|
|
171
171
|
// only via the rollout below — so take the version from the publish reply,
|
|
172
172
|
// not from active_version (which hasn't advanced yet).
|
|
173
|
-
const pub = await icRequest(i.baseUrl, i.token, "POST", `/v1/
|
|
173
|
+
const pub = await icRequest(i.baseUrl, i.token, "POST", `/v1/agents/${id}/versions`, {
|
|
174
174
|
note: i.publishNote ?? null,
|
|
175
175
|
});
|
|
176
176
|
version = pub.version;
|
|
@@ -178,43 +178,43 @@ async function reconcileBlueprint(i, knownId, priorSig) {
|
|
|
178
178
|
// Always assert the rollout: it activates a freshly published version and is
|
|
179
179
|
// an idempotent no-op when `version` is already the active one at `percent`.
|
|
180
180
|
const percent = i.rolloutPercent ?? 100;
|
|
181
|
-
await icRequest(i.baseUrl, i.token, "POST", `/v1/
|
|
181
|
+
await icRequest(i.baseUrl, i.token, "POST", `/v1/agents/${id}/rollout`, { version, percent });
|
|
182
182
|
return {
|
|
183
183
|
...i,
|
|
184
|
-
|
|
184
|
+
agentId: id,
|
|
185
185
|
contentSig: desiredSig,
|
|
186
186
|
activeVersion: version,
|
|
187
187
|
rolloutPercent: percent,
|
|
188
188
|
};
|
|
189
189
|
}
|
|
190
|
-
const
|
|
190
|
+
const agentProvider = {
|
|
191
191
|
async create(i) {
|
|
192
|
-
const outs = await
|
|
193
|
-
return { id: outs.
|
|
192
|
+
const outs = await reconcileAgent(i);
|
|
193
|
+
return { id: outs.agentId, outs };
|
|
194
194
|
},
|
|
195
195
|
async update(id, olds, news) {
|
|
196
|
-
const outs = await
|
|
196
|
+
const outs = await reconcileAgent(news, id, olds.contentSig);
|
|
197
197
|
return { outs };
|
|
198
198
|
},
|
|
199
199
|
async delete(id, props) {
|
|
200
200
|
try {
|
|
201
|
-
await icRequest(props.baseUrl, props.token, "DELETE", `/v1/
|
|
201
|
+
await icRequest(props.baseUrl, props.token, "DELETE", `/v1/agents/${id}`);
|
|
202
202
|
}
|
|
203
203
|
catch (e) {
|
|
204
|
-
throw new Error(`
|
|
204
|
+
throw new Error(`Agent ${id} could not be archived (it likely still has smiths attached). ` +
|
|
205
205
|
`Detach its users first, or set { retainOnDelete: true } on the resource. ` +
|
|
206
206
|
`Original error: ${e}`);
|
|
207
207
|
}
|
|
208
208
|
},
|
|
209
209
|
async diff(_id, olds, news) {
|
|
210
|
-
const contentChanged =
|
|
210
|
+
const contentChanged = agentContentSig(olds) !== agentContentSig(news);
|
|
211
211
|
const nameChanged = olds.name !== news.name;
|
|
212
212
|
const rolloutChanged = (olds.rolloutPercent ?? 100) !== (news.rolloutPercent ?? 100);
|
|
213
213
|
return { changes: contentChanged || nameChanged || rolloutChanged };
|
|
214
214
|
},
|
|
215
|
-
// Adopt a
|
|
215
|
+
// Adopt a agent a script already created (`pulumi import <id>`).
|
|
216
216
|
async read(id, props) {
|
|
217
|
-
const bp = await icRequest(props.baseUrl, props.token, "GET", `/v1/
|
|
217
|
+
const bp = await icRequest(props.baseUrl, props.token, "GET", `/v1/agents/${id}`);
|
|
218
218
|
if (!bp || !bp.id)
|
|
219
219
|
return { id, props: props };
|
|
220
220
|
const d = bp.draft ?? {};
|
|
@@ -232,9 +232,9 @@ const blueprintProvider = {
|
|
|
232
232
|
};
|
|
233
233
|
},
|
|
234
234
|
};
|
|
235
|
-
class
|
|
235
|
+
class IcAgent extends pulumi.dynamic.Resource {
|
|
236
236
|
constructor(name, args, opts) {
|
|
237
|
-
super(
|
|
237
|
+
super(agentProvider, name, {
|
|
238
238
|
instructions: undefined,
|
|
239
239
|
model: undefined,
|
|
240
240
|
enabledHostedTools: undefined,
|
|
@@ -242,14 +242,14 @@ class IcBlueprint extends pulumi.dynamic.Resource {
|
|
|
242
242
|
variables: undefined,
|
|
243
243
|
publishNote: undefined,
|
|
244
244
|
rolloutPercent: undefined,
|
|
245
|
-
|
|
245
|
+
agentId: undefined,
|
|
246
246
|
activeVersion: undefined,
|
|
247
247
|
contentSig: undefined,
|
|
248
248
|
...args,
|
|
249
249
|
}, { ...opts, additionalSecretOutputs: ["token"] });
|
|
250
250
|
}
|
|
251
251
|
}
|
|
252
|
-
exports.
|
|
252
|
+
exports.IcAgent = IcAgent;
|
|
253
253
|
function mcpBody(i) {
|
|
254
254
|
const auth = { kind: i.authKind };
|
|
255
255
|
if (i.authProvider)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ingram-tech/pulumi-ingram-cloud",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Pulumi dynamic resources for the Ingram Cloud /v1 API —
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Pulumi dynamic resources for the Ingram Cloud /v1 API — agents, MCP servers, channels, webhooks, model keys.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|