@aws/nx-plugin 1.0.0-rc.67 → 1.0.0-rc.69

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.
Files changed (53) hide show
  1. package/README.md +1 -0
  2. package/generators.json +7 -0
  3. package/migrations.json +6 -1
  4. package/package.json +1 -1
  5. package/src/agentcore-harness/__snapshots__/generator.spec.ts.snap +238 -0
  6. package/src/agentcore-harness/files/project/README.md.template +83 -0
  7. package/src/agentcore-harness/files/project/scripts/chat.ts.template +99 -0
  8. package/src/agentcore-harness/files/project/src/PROMPT.md.template +16 -0
  9. package/src/agentcore-harness/generator.d.ts +62 -0
  10. package/src/agentcore-harness/generator.js +158 -0
  11. package/src/agentcore-harness/generator.js.map +1 -0
  12. package/src/agentcore-harness/schema.d.js +8 -0
  13. package/src/agentcore-harness/schema.d.js.map +1 -0
  14. package/src/agentcore-harness/schema.d.ts +17 -0
  15. package/src/agentcore-harness/schema.json +53 -0
  16. package/src/migrations/latest/translate-script-whole-file-writes/files/build-system-prompt.ts.fixture +23 -0
  17. package/src/migrations/latest/translate-script-whole-file-writes/files/build-user-prompt.ts.fixture +96 -0
  18. package/src/migrations/latest/translate-script-whole-file-writes/files/config-path.ts.fixture +1 -0
  19. package/src/migrations/latest/translate-script-whole-file-writes/files/file-to-translate.ts.fixture +10 -0
  20. package/src/migrations/latest/translate-script-whole-file-writes/files/get-files-to-translate.ts.fixture +96 -0
  21. package/src/migrations/latest/translate-script-whole-file-writes/files/header.ts.fixture +15 -0
  22. package/src/migrations/latest/translate-script-whole-file-writes/files/log.ts.fixture +18 -0
  23. package/src/migrations/latest/translate-script-whole-file-writes/files/main-call.ts.fixture +6 -0
  24. package/src/migrations/latest/translate-script-whole-file-writes/files/main.ts.fixture +79 -0
  25. package/src/migrations/latest/translate-script-whole-file-writes/files/project-root.ts.fixture +1 -0
  26. package/src/migrations/latest/translate-script-whole-file-writes/files/run-with-concurrency.ts.fixture +57 -0
  27. package/src/migrations/latest/translate-script-whole-file-writes/files/scripts-dir.ts.fixture +1 -0
  28. package/src/migrations/latest/translate-script-whole-file-writes/files/translate-file-for-language.ts.fixture +61 -0
  29. package/src/migrations/latest/translate-script-whole-file-writes/grit/already-migrated.grit +1 -0
  30. package/src/migrations/latest/translate-script-whole-file-writes/grit/build-system-prompt.grit +6 -0
  31. package/src/migrations/latest/translate-script-whole-file-writes/grit/build-user-prompt.grit +6 -0
  32. package/src/migrations/latest/translate-script-whole-file-writes/grit/config-path.grit +1 -0
  33. package/src/migrations/latest/translate-script-whole-file-writes/grit/file-to-translate.grit +11 -0
  34. package/src/migrations/latest/translate-script-whole-file-writes/grit/get-files-to-translate.grit +7 -0
  35. package/src/migrations/latest/translate-script-whole-file-writes/grit/log.grit +3 -0
  36. package/src/migrations/latest/translate-script-whole-file-writes/grit/main-call.grit +1 -0
  37. package/src/migrations/latest/translate-script-whole-file-writes/grit/main.grit +8 -0
  38. package/src/migrations/latest/translate-script-whole-file-writes/grit/project-root.grit +1 -0
  39. package/src/migrations/latest/translate-script-whole-file-writes/grit/run-with-concurrency.grit +6 -0
  40. package/src/migrations/latest/translate-script-whole-file-writes/grit/translate-file-for-language.grit +6 -0
  41. package/src/migrations/latest/translate-script-whole-file-writes/metadata.json +3 -0
  42. package/src/migrations/latest/translate-script-whole-file-writes/migration.d.ts +2 -0
  43. package/src/migrations/latest/translate-script-whole-file-writes/migration.js +103 -0
  44. package/src/migrations/latest/translate-script-whole-file-writes/migration.js.map +1 -0
  45. package/src/migrations/latest/translate-script-whole-file-writes/test-fixtures/released-script-first.ts.fixture +430 -0
  46. package/src/migrations/latest/translate-script-whole-file-writes/test-fixtures/released-script.ts.fixture +431 -0
  47. package/src/preset/__snapshots__/generator.spec.ts.snap +2 -0
  48. package/src/ts/astro-docs/files/translation/scripts/translate.ts.template +269 -148
  49. package/src/utils/agent-core-constructs/agent-core-constructs.d.ts +25 -0
  50. package/src/utils/agent-core-constructs/agent-core-constructs.js +59 -0
  51. package/src/utils/agent-core-constructs/agent-core-constructs.js.map +1 -1
  52. package/src/utils/agent-core-constructs/files/cdk/app/agentcore-harness/__nameKebabCase__/__nameKebabCase__.ts.template +366 -0
  53. package/src/utils/agent-core-constructs/files/terraform/app/agentcore-harness/__nameKebabCase__/__nameKebabCase__.tf.template +282 -0
package/README.md CHANGED
@@ -177,6 +177,7 @@ pnpm nx g @aws/nx-plugin:ts#infra
177
177
  | `py#lambda-function` | Python Lambda with type-safe event sources |
178
178
  | `py#mcp-server` | MCP server (Python) |
179
179
  | `py#agent` | [Strands Agent](https://strandsagents.com/) (Python) |
180
+ | `agentcore-harness` | [AgentCore Harness](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/harness.html) agent loop |
180
181
  | `connection` | Connect projects together (e.g. frontend to API) |
181
182
  | `terraform#project` | Terraform project |
182
183
  | `license` | Manage LICENSE files and source headers |
package/generators.json CHANGED
@@ -44,6 +44,13 @@
44
44
  "metric": "g70",
45
45
  "hidden": true
46
46
  },
47
+ "agentcore-harness": {
48
+ "factory": "./src/agentcore-harness/generator",
49
+ "schema": "./src/agentcore-harness/schema.json",
50
+ "description": "Generate an AgentCore Harness project",
51
+ "metric": "g71",
52
+ "guidePages": ["agentcore-harness"]
53
+ },
47
54
  "connection": {
48
55
  "factory": "./src/connection/generator",
49
56
  "schema": "./src/connection/schema.json",
package/migrations.json CHANGED
@@ -7,6 +7,11 @@
7
7
  "description": "Move Smithy APIs onto the renamed @smithy/server-* packages",
8
8
  "implementation": "./src/migrations/latest/smithy-server-package-rename/migration"
9
9
  },
10
+ "latest-translate-script-whole-file-writes": {
11
+ "version": "1.0.0-rc.68",
12
+ "description": "Update the docs translate script to write whole translated files rather than editing them in place",
13
+ "implementation": "./src/migrations/latest/translate-script-whole-file-writes/migration"
14
+ },
10
15
  "v1.0.0-rc.50-0001-modernize-function-props-cast": {
11
16
  "version": "1.0.0-rc.50",
12
17
  "description": "Replace the legacy angle-bracket FunctionProps type assertion with the modern as syntax in generated API constructs",
@@ -103,7 +108,7 @@
103
108
  "implementation": "./src/migrations/v1.0.0-rc.65/0002-rolldown-code-splitting/migration"
104
109
  },
105
110
  "sync-vended-versions": {
106
- "version": "1.0.0-rc.67",
111
+ "version": "1.0.0-rc.69",
107
112
  "description": "Sync vended dependency versions and the tracked plugin version to those vended by this release",
108
113
  "implementation": "./src/utils/version-upgrade-migration/migration"
109
114
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aws/nx-plugin",
3
- "version": "1.0.0-rc.67",
3
+ "version": "1.0.0-rc.69",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/awslabs/nx-plugin-for-aws.git",
@@ -0,0 +1,238 @@
1
+ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
+
3
+ exports[`agentcore-harness generator > snapshot > snapshots the four rendered harness project files > packages/my-harness/README.md 1`] = `
4
+ "# @proj/my-harness
5
+
6
+ An [Amazon Bedrock AgentCore Harness](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/harness.html)
7
+ project generated with [@aws/nx-plugin](https://github.com/awslabs/nx-plugin-for-aws/).
8
+ A Harness is a managed agent loop that AWS runs for you, so this project
9
+ holds only the prompt that shapes it and a script for talking to it:
10
+
11
+ - \`src/PROMPT.md\` — the system prompt
12
+ - \`scripts/chat.ts\` — a multi-turn chat client for the deployed Harness
13
+ - \`project.json\` — declares the \`chat\` target
14
+ - \`README.md\` — this file
15
+
16
+ The Harness itself is deployed by the generated CDK construct or Terraform
17
+ module through your usual infrastructure workflow.
18
+
19
+ ## The system prompt
20
+
21
+ \`src/PROMPT.md\` is the Harness system prompt. Your infrastructure reads the
22
+ file when you synthesize (CDK) or plan (Terraform), so edit it and redeploy
23
+ to change how the Harness behaves.
24
+
25
+ The prompt is deployment configuration rather than secret storage: its
26
+ contents appear in the synthesized CloudFormation template or in Terraform
27
+ state.
28
+
29
+ ## Chatting with your Harness
30
+
31
+ \`\`\`bash
32
+ pnpm nx run @proj/my-harness:chat
33
+ \`\`\`
34
+
35
+ Every turn of a run shares one session, so the Harness keeps the
36
+ conversation context until you exit.
37
+
38
+ The Harness ARN is resolved in this order:
39
+
40
+ 1. \`HARNESS_ARN\`, used directly:
41
+
42
+ \`\`\`bash
43
+ HARNESS_ARN=<harness-arn> pnpm nx run @proj/my-harness:chat
44
+ \`\`\`
45
+
46
+ 2. \`RUNTIME_CONFIG_APP_ID\`, which reads the
47
+ \`agentcore.harnesses.MyHarness\` entry your deployed
48
+ infrastructure publishes:
49
+
50
+ \`\`\`bash
51
+ RUNTIME_CONFIG_APP_ID=<application-id> pnpm nx run @proj/my-harness:chat
52
+ \`\`\`
53
+
54
+ With neither set, the script fails with an error naming both. The AWS Region
55
+ is derived from the Harness ARN, and credentials come from the standard AWS
56
+ SDK credential provider chain.
57
+
58
+ A caller needs \`bedrock-agentcore:InvokeHarness\` and
59
+ \`bedrock-agentcore:InvokeAgentRuntime\` on the Harness ARN. The CDK
60
+ construct's \`grantInvokeAccess\` grants exactly those two actions.
61
+
62
+ ## Customizing your Harness
63
+
64
+ Edit \`src/PROMPT.md\` for the system prompt. Everything else is configured
65
+ where you instantiate the infrastructure — including tools, which the
66
+ Harness deploys without:
67
+
68
+ - CDK construct props, for example
69
+ \`new MyHarness(this, 'MyHarness', { allowedTools: ['@builtin'] })\`
70
+ - Terraform, by setting \`allowed_tools = ["@builtin"]\` on the module's
71
+ \`aws_bedrockagentcore_harness\` resource, or by adding an \`allowed_tools\`
72
+ variable if you would rather set it as a module argument
73
+
74
+ The generated infrastructure is also yours to edit directly:
75
+
76
+ - \`packages/common/constructs/src/app/harnesses/my-harness/my-harness.ts\`
77
+ - \`packages/common/terraform/src/app/harnesses/my-harness/my-harness.tf\`
78
+
79
+ Re-running the generator only adds missing files, so your edits to these
80
+ files and to \`src/PROMPT.md\` are preserved.
81
+
82
+ ## Further reading
83
+
84
+ - [AgentCore Harness guide](https://awslabs.github.io/nx-plugin-for-aws/guides/agentcore-harness/)
85
+ - [Amazon Bedrock AgentCore Harness documentation](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/harness.html)
86
+ - [Learn more about Nx](https://nx.dev/getting-started/intro)
87
+ "
88
+ `;
89
+
90
+ exports[`agentcore-harness generator > snapshot > snapshots the four rendered harness project files > packages/my-harness/project.json 1`] = `
91
+ "{
92
+ "name": "@proj/my-harness",
93
+ "$schema": "../../node_modules/nx/schemas/project-schema.json",
94
+ "projectType": "application",
95
+ "sourceRoot": "packages/my-harness",
96
+ "tags": [],
97
+ "metadata": {
98
+ "generator": "agentcore-harness",
99
+ "name": "my-harness",
100
+ "rc": "MyHarness",
101
+ "auth": "iam",
102
+ "iac": "cdk"
103
+ },
104
+ "targets": {
105
+ "chat": {
106
+ "executor": "nx:run-commands",
107
+ "options": {
108
+ "commands": ["tsx ./scripts/chat.ts"],
109
+ "cwd": "{projectRoot}"
110
+ }
111
+ }
112
+ }
113
+ }
114
+ "
115
+ `;
116
+
117
+ exports[`agentcore-harness generator > snapshot > snapshots the four rendered harness project files > packages/my-harness/scripts/chat.ts 1`] = `
118
+ "// Chat CLI for MyHarness. Invokes the deployed Harness with InvokeHarness.
119
+ import { randomUUID } from 'node:crypto';
120
+ import { getAppConfig } from '@aws-lambda-powertools/parameters/appconfig';
121
+ import {
122
+ BedrockAgentCoreClient,
123
+ InvokeHarnessCommand,
124
+ } from '@aws-sdk/client-bedrock-agentcore';
125
+ import { chatLoop, type ChatAdapter } from 'agent-chat-cli';
126
+
127
+ // The deployed infrastructure publishes the Harness ARN at
128
+ // \`agentcore.harnesses.MyHarness\`.
129
+ const HARNESS_RUNTIME_CONFIG_KEY = 'MyHarness';
130
+
131
+ // One session id per run, so every turn continues the same Harness session.
132
+ const SESSION_ID = randomUUID();
133
+
134
+ // Empty strings count as absent, so \`HARNESS_ARN= nx run ...\` still discovers.
135
+ const isPresent = (value: string | undefined): value is string =>
136
+ value !== undefined && value !== '';
137
+
138
+ // \`HARNESS_ARN\` wins; \`RUNTIME_CONFIG_APP_ID\` reads the runtime configuration.
139
+ const resolveHarnessArn = async (): Promise<string> => {
140
+ if (isPresent(process.env.HARNESS_ARN)) {
141
+ return process.env.HARNESS_ARN;
142
+ }
143
+ const application = process.env.RUNTIME_CONFIG_APP_ID;
144
+ if (!isPresent(application)) {
145
+ throw new Error(
146
+ 'No Harness ARN source is configured. Set HARNESS_ARN to the deployed ' +
147
+ 'Harness ARN directly, or set RUNTIME_CONFIG_APP_ID to the AppConfig ' +
148
+ 'application ID emitted by your infrastructure stack.',
149
+ );
150
+ }
151
+ const config = (await getAppConfig('agentcore', {
152
+ application,
153
+ environment: 'default',
154
+ transform: 'json',
155
+ })) as { harnesses?: Record<string, string | undefined> };
156
+ const harnessArn = config?.harnesses?.[HARNESS_RUNTIME_CONFIG_KEY];
157
+ if (!harnessArn) {
158
+ throw new Error(
159
+ \`Runtime configuration for application '\${application}' has no value \` +
160
+ \`at 'agentcore.harnesses.\${HARNESS_RUNTIME_CONFIG_KEY}'. Deploy the \` +
161
+ 'Harness infrastructure first, or set HARNESS_ARN directly.',
162
+ );
163
+ }
164
+ return harnessArn;
165
+ };
166
+
167
+ const HARNESS_ARN = await resolveHarnessArn();
168
+
169
+ // Region comes from the ARN, and credentials from the standard AWS SDK
170
+ // default provider chain, so no Region is embedded in this project.
171
+ const client = new BedrockAgentCoreClient({
172
+ region: HARNESS_ARN.split(':')[3],
173
+ });
174
+
175
+ class HarnessAdapter implements ChatAdapter {
176
+ async connect() {
177
+ return { agentName: 'MyHarness' };
178
+ }
179
+
180
+ async *sendMessage(text: string): AsyncIterable<string> {
181
+ const { stream } = await client.send(
182
+ new InvokeHarnessCommand({
183
+ harnessArn: HARNESS_ARN,
184
+ runtimeSessionId: SESSION_ID,
185
+ messages: [{ role: 'user', content: [{ text }] }],
186
+ }),
187
+ );
188
+ if (!stream) {
189
+ throw new Error(
190
+ 'AgentCore returned no event stream for the invocation. Confirm the ' +
191
+ 'Harness is deployed and the caller has the ' +
192
+ 'bedrock-agentcore:InvokeHarness permission.',
193
+ );
194
+ }
195
+ for await (const event of stream) {
196
+ const serviceError =
197
+ event.internalServerException ??
198
+ event.validationException ??
199
+ event.runtimeClientError;
200
+ if (serviceError) {
201
+ const detail = [serviceError.name, serviceError.message]
202
+ .filter(Boolean)
203
+ .join(': ');
204
+ throw new Error(
205
+ \`Harness invocation failed: \${detail || JSON.stringify(serviceError)}\`,
206
+ );
207
+ }
208
+ const chunk = event.contentBlockDelta?.delta?.text;
209
+ if (chunk) {
210
+ yield chunk;
211
+ }
212
+ }
213
+ }
214
+ }
215
+
216
+ await chatLoop(new HarnessAdapter(), '');
217
+ "
218
+ `;
219
+
220
+ exports[`agentcore-harness generator > snapshot > snapshots the four rendered harness project files > packages/my-harness/src/PROMPT.md 1`] = `
221
+ "# MyHarness
222
+
223
+ You are a helpful AI assistant.
224
+
225
+ ## Responding
226
+
227
+ - Lead with the answer, then the supporting detail.
228
+ - Keep the response proportional to the request: short answers to simple
229
+ questions, thorough answers to involved ones.
230
+ - Ask for the detail you need when a request is ambiguous instead of guessing.
231
+ - Say when you do not know something, and say what would settle it.
232
+
233
+ ## Using tools
234
+
235
+ When tools are available, prefer them over recollection for anything you can
236
+ look up, and report what a tool returned, including when it fails.
237
+ "
238
+ `;
@@ -0,0 +1,83 @@
1
+ # <%- fullyQualifiedName %>
2
+
3
+ An [Amazon Bedrock AgentCore Harness](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/harness.html)
4
+ project generated with [@aws/nx-plugin](https://github.com/awslabs/nx-plugin-for-aws/).
5
+ A Harness is a managed agent loop that AWS runs for you, so this project
6
+ holds only the prompt that shapes it and a script for talking to it:
7
+
8
+ - `src/PROMPT.md` — the system prompt
9
+ - `scripts/chat.ts` — a multi-turn chat client for the deployed Harness
10
+ - `project.json` — declares the `chat` target
11
+ - `README.md` — this file
12
+
13
+ The Harness itself is deployed by the generated CDK construct or Terraform
14
+ module through your usual infrastructure workflow.
15
+
16
+ ## The system prompt
17
+
18
+ `src/PROMPT.md` is the Harness system prompt. Your infrastructure reads the
19
+ file when you synthesize (CDK) or plan (Terraform), so edit it and redeploy
20
+ to change how the Harness behaves.
21
+
22
+ The prompt is deployment configuration rather than secret storage: its
23
+ contents appear in the synthesized CloudFormation template or in Terraform
24
+ state.
25
+
26
+ ## Chatting with your Harness
27
+
28
+ ```bash
29
+ pnpm nx run <%- fullyQualifiedName %>:chat
30
+ ```
31
+
32
+ Every turn of a run shares one session, so the Harness keeps the
33
+ conversation context until you exit.
34
+
35
+ The Harness ARN is resolved in this order:
36
+
37
+ 1. `HARNESS_ARN`, used directly:
38
+
39
+ ```bash
40
+ HARNESS_ARN=<harness-arn> pnpm nx run <%- fullyQualifiedName %>:chat
41
+ ```
42
+
43
+ 2. `RUNTIME_CONFIG_APP_ID`, which reads the
44
+ `agentcore.harnesses.<%- nameClassName %>` entry your deployed
45
+ infrastructure publishes:
46
+
47
+ ```bash
48
+ RUNTIME_CONFIG_APP_ID=<application-id> pnpm nx run <%- fullyQualifiedName %>:chat
49
+ ```
50
+
51
+ With neither set, the script fails with an error naming both. The AWS Region
52
+ is derived from the Harness ARN, and credentials come from the standard AWS
53
+ SDK credential provider chain.
54
+
55
+ A caller needs `bedrock-agentcore:InvokeHarness` and
56
+ `bedrock-agentcore:InvokeAgentRuntime` on the Harness ARN. The CDK
57
+ construct's `grantInvokeAccess` grants exactly those two actions.
58
+
59
+ ## Customizing your Harness
60
+
61
+ Edit `src/PROMPT.md` for the system prompt. Everything else is configured
62
+ where you instantiate the infrastructure — including tools, which the
63
+ Harness deploys without:
64
+
65
+ - CDK construct props, for example
66
+ `new <%- nameClassName %>(this, '<%- nameClassName %>', { allowedTools: ['@builtin'] })`
67
+ - Terraform, by setting `allowed_tools = ["@builtin"]` on the module's
68
+ `aws_bedrockagentcore_harness` resource, or by adding an `allowed_tools`
69
+ variable if you would rather set it as a module argument
70
+
71
+ The generated infrastructure is also yours to edit directly:
72
+
73
+ - `packages/common/constructs/src/app/harnesses/<%- nameKebabCase %>/<%- nameKebabCase %>.ts`
74
+ - `packages/common/terraform/src/app/harnesses/<%- nameKebabCase %>/<%- nameKebabCase %>.tf`
75
+
76
+ Re-running the generator only adds missing files, so your edits to these
77
+ files and to `src/PROMPT.md` are preserved.
78
+
79
+ ## Further reading
80
+
81
+ - [AgentCore Harness guide](https://awslabs.github.io/nx-plugin-for-aws/guides/agentcore-harness/)
82
+ - [Amazon Bedrock AgentCore Harness documentation](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/harness.html)
83
+ - [Learn more about Nx](https://nx.dev/getting-started/intro)
@@ -0,0 +1,99 @@
1
+ // Chat CLI for <%- nameClassName %>. Invokes the deployed Harness with InvokeHarness.
2
+ import { randomUUID } from 'node:crypto';
3
+ import { getAppConfig } from '@aws-lambda-powertools/parameters/appconfig';
4
+ import {
5
+ BedrockAgentCoreClient,
6
+ InvokeHarnessCommand,
7
+ } from '@aws-sdk/client-bedrock-agentcore';
8
+ import { chatLoop, type ChatAdapter } from 'agent-chat-cli';
9
+
10
+ // The deployed infrastructure publishes the Harness ARN at
11
+ // `agentcore.harnesses.<%- nameClassName %>`.
12
+ const HARNESS_RUNTIME_CONFIG_KEY = '<%- nameClassName %>';
13
+
14
+ // One session id per run, so every turn continues the same Harness session.
15
+ const SESSION_ID = randomUUID();
16
+
17
+ // Empty strings count as absent, so `HARNESS_ARN= nx run ...` still discovers.
18
+ const isPresent = (value: string | undefined): value is string =>
19
+ value !== undefined && value !== '';
20
+
21
+ // `HARNESS_ARN` wins; `RUNTIME_CONFIG_APP_ID` reads the runtime configuration.
22
+ const resolveHarnessArn = async (): Promise<string> => {
23
+ if (isPresent(process.env.HARNESS_ARN)) {
24
+ return process.env.HARNESS_ARN;
25
+ }
26
+ const application = process.env.RUNTIME_CONFIG_APP_ID;
27
+ if (!isPresent(application)) {
28
+ throw new Error(
29
+ 'No Harness ARN source is configured. Set HARNESS_ARN to the deployed ' +
30
+ 'Harness ARN directly, or set RUNTIME_CONFIG_APP_ID to the AppConfig ' +
31
+ 'application ID emitted by your infrastructure stack.',
32
+ );
33
+ }
34
+ const config = (await getAppConfig('agentcore', {
35
+ application,
36
+ environment: 'default',
37
+ transform: 'json',
38
+ })) as { harnesses?: Record<string, string | undefined> };
39
+ const harnessArn = config?.harnesses?.[HARNESS_RUNTIME_CONFIG_KEY];
40
+ if (!harnessArn) {
41
+ throw new Error(
42
+ `Runtime configuration for application '${application}' has no value ` +
43
+ `at 'agentcore.harnesses.${HARNESS_RUNTIME_CONFIG_KEY}'. Deploy the ` +
44
+ 'Harness infrastructure first, or set HARNESS_ARN directly.',
45
+ );
46
+ }
47
+ return harnessArn;
48
+ };
49
+
50
+ const HARNESS_ARN = await resolveHarnessArn();
51
+
52
+ // Region comes from the ARN, and credentials from the standard AWS SDK
53
+ // default provider chain, so no Region is embedded in this project.
54
+ const client = new BedrockAgentCoreClient({
55
+ region: HARNESS_ARN.split(':')[3],
56
+ });
57
+
58
+ class HarnessAdapter implements ChatAdapter {
59
+ async connect() {
60
+ return { agentName: '<%- nameClassName %>' };
61
+ }
62
+
63
+ async *sendMessage(text: string): AsyncIterable<string> {
64
+ const { stream } = await client.send(
65
+ new InvokeHarnessCommand({
66
+ harnessArn: HARNESS_ARN,
67
+ runtimeSessionId: SESSION_ID,
68
+ messages: [{ role: 'user', content: [{ text }] }],
69
+ }),
70
+ );
71
+ if (!stream) {
72
+ throw new Error(
73
+ 'AgentCore returned no event stream for the invocation. Confirm the ' +
74
+ 'Harness is deployed and the caller has the ' +
75
+ 'bedrock-agentcore:InvokeHarness permission.',
76
+ );
77
+ }
78
+ for await (const event of stream) {
79
+ const serviceError =
80
+ event.internalServerException ??
81
+ event.validationException ??
82
+ event.runtimeClientError;
83
+ if (serviceError) {
84
+ const detail = [serviceError.name, serviceError.message]
85
+ .filter(Boolean)
86
+ .join(': ');
87
+ throw new Error(
88
+ `Harness invocation failed: ${detail || JSON.stringify(serviceError)}`,
89
+ );
90
+ }
91
+ const chunk = event.contentBlockDelta?.delta?.text;
92
+ if (chunk) {
93
+ yield chunk;
94
+ }
95
+ }
96
+ }
97
+ }
98
+
99
+ await chatLoop(new HarnessAdapter(), '');
@@ -0,0 +1,16 @@
1
+ # <%- nameClassName %>
2
+
3
+ You are a helpful AI assistant.
4
+
5
+ ## Responding
6
+
7
+ - Lead with the answer, then the supporting detail.
8
+ - Keep the response proportional to the request: short answers to simple
9
+ questions, thorough answers to involved ones.
10
+ - Ask for the detail you need when a request is ambiguous instead of guessing.
11
+ - Say when you do not know something, and say what would settle it.
12
+
13
+ ## Using tools
14
+
15
+ When tools are available, prefer them over recollection for anything you can
16
+ look up, and report what a tool returned, including when it fails.
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { type GeneratorCallback, type ProjectConfiguration, type Tree } from '@nx/devkit';
6
+ import { type NxGeneratorInfo } from '../utils/nx';
7
+ import type { IacMetadata } from '../utils/shared-constructs-constants';
8
+ import type { AgentcoreHarnessGeneratorSchema } from './schema';
9
+ export declare const DEPENDENCIES: import("../utils/declared-dependencies").DependencyDeclaration<readonly [{
10
+ readonly name: "@aws-sdk/client-bedrock-agentcore";
11
+ readonly root: true;
12
+ }, {
13
+ readonly name: "@aws-sdk/client-appconfigdata";
14
+ readonly root: true;
15
+ }, {
16
+ readonly name: "@aws-lambda-powertools/parameters";
17
+ readonly root: true;
18
+ }, {
19
+ readonly name: "agent-chat-cli";
20
+ readonly root: true;
21
+ }, {
22
+ readonly name: "@types/node";
23
+ readonly dev: true;
24
+ readonly root: true;
25
+ }, {
26
+ readonly name: "tsx";
27
+ readonly dev: true;
28
+ readonly root: true;
29
+ }, {
30
+ readonly name: "constructs";
31
+ readonly when: (m: IacMetadata) => boolean;
32
+ } & {
33
+ versionOnly: true;
34
+ }, {
35
+ readonly name: "aws-cdk-lib";
36
+ readonly when: (m: IacMetadata) => boolean;
37
+ } & {
38
+ versionOnly: true;
39
+ }, {
40
+ readonly name: "@types/node";
41
+ } & {
42
+ versionOnly: true;
43
+ }], readonly import("../utils/declared-dependencies").DeclaredPyDependency<"a2a-sdk" | "ag-ui-langgraph" | "ag-ui-protocol" | "ag-ui-strands" | "aws-lambda-powertools" | "aws-lambda-powertools[tracer]" | "aws-lambda-powertools[parser]" | "aws-opentelemetry-distro" | "bedrock-agentcore" | "boto3" | "checkov" | "fastapi" | "fastapi[standard]" | "httpx" | "langchain" | "langchain-aws" | "langchain-mcp-adapters" | "langgraph" | "mcp" | "pip-check-updates" | "pip-licenses" | "ruff" | "strands-agents" | "strands-agents[a2a]" | "strands-agents-tools" | "ty" | "pynamodb" | "uvicorn" | "sqlmodel" | "alembic" | "aiomysql" | "asyncpg" | "greenlet", AgentCoreHarnessMetadata>[]>;
44
+ export declare const AGENTCORE_HARNESS_GENERATOR_INFO: NxGeneratorInfo;
45
+ export declare const agentcoreHarnessGenerator: (tree: Tree, options: AgentcoreHarnessGeneratorSchema) => Promise<GeneratorCallback>;
46
+ /**
47
+ * Harness details stored in the Harness Project's metadata. `iac` records which
48
+ * provider's infrastructure was written, so the version sync can tell which
49
+ * shared constructs packages this project owns.
50
+ */
51
+ export interface AgentCoreHarnessMetadata extends IacMetadata {
52
+ generator: string;
53
+ name: string;
54
+ rc: string;
55
+ auth: 'iam';
56
+ }
57
+ /**
58
+ * Read a Harness Project's metadata, validating it was generated by the
59
+ * agentcore-harness generator before returning typed data.
60
+ */
61
+ export declare const readAgentCoreHarnessMetadata: (project: ProjectConfiguration) => AgentCoreHarnessMetadata;
62
+ export default agentcoreHarnessGenerator;