@promptbook/cli 0.112.0-112 → 0.112.0-113
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 +7 -7
- package/apps/agents-server/README.md +1 -1
- package/apps/agents-server/next.config.ts +20 -1
- package/apps/agents-server/src/app/api/admin/code-runners/route.ts +1 -1
- package/apps/agents-server/src/app/api/internal/user-chat-jobs/run/route.ts +1 -1
- package/apps/agents-server/src/instrumentation-client.ts +28 -0
- package/apps/agents-server/src/instrumentation.ts +16 -0
- package/apps/agents-server/src/sentry.edge.config.ts +18 -0
- package/apps/agents-server/src/sentry.server.config.ts +19 -0
- package/apps/agents-server/src/utils/codeRunnerConfiguration.ts +1 -1
- package/apps/agents-server/src/utils/errorReporting/agentsServerSentryContext.ts +203 -0
- package/apps/agents-server/src/utils/errorReporting/registerServerErrorSentryLogging.ts +59 -9
- package/apps/agents-server/src/utils/errorReporting/sendApplicationErrorReportToSentry.ts +39 -3
- package/apps/agents-server/src/utils/errorReporting/sentrySdkConfig.ts +237 -0
- package/apps/agents-server/src/utils/errorReporting/sentryStore.ts +10 -0
- package/apps/agents-server/src/utils/externalChatRunner/createExternalAgentRepositoryFiles.ts +2 -2
- package/apps/agents-server/src/utils/userChat/triggerUserChatJobWorker.ts +54 -19
- package/apps/agents-server/src/utils/vpsConfiguration.ts +1 -1
- package/esm/index.es.js +9325 -8883
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-agent-chat/executeAgentChatTurn.d.ts +28 -0
- package/esm/scripts/run-agent-chat/runAgentChat.d.ts +5 -0
- package/esm/scripts/run-agent-chat/runAgentExec.d.ts +11 -0
- package/esm/scripts/run-agent-messages/messages/createAgentRunnerSystemMessage.d.ts +10 -0
- package/esm/scripts/run-codex-prompts/common/resolveInlineOrFileText.d.ts +14 -0
- package/esm/src/_packages/node.index.d.ts +20 -0
- package/esm/src/_packages/types.index.d.ts +16 -0
- package/esm/src/book-3.0/BookNodeAgentSource.d.ts +38 -0
- package/esm/src/book-3.0/CliAgent.d.ts +68 -0
- package/esm/src/book-3.0/LiteAgent.d.ts +68 -0
- package/esm/src/book-components/BookEditor/BookEditorAboutPromptbookInformation.d.ts +12 -0
- package/esm/src/cli/cli-commands/agent/agentCliOptions.d.ts +29 -0
- package/esm/src/cli/cli-commands/agent/chat.d.ts +10 -0
- package/esm/src/cli/cli-commands/agent/exec.d.ts +10 -0
- package/esm/src/cli/cli-commands/agent/run.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/agent.d.ts +14 -0
- package/esm/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +3 -4
- package/esm/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +9 -9
- package/esm/src/version.d.ts +1 -1
- package/package.json +2 -1
- package/src/_packages/node.index.ts +20 -0
- package/src/_packages/types.index.ts +16 -0
- package/src/book-3.0/BookNodeAgentSource.ts +135 -0
- package/src/book-3.0/CliAgent.ts +236 -0
- package/src/book-3.0/LiteAgent.ts +463 -0
- package/src/book-components/BookEditor/BookEditor.module.css +61 -0
- package/src/book-components/BookEditor/BookEditorAboutPromptbookInformation.tsx +74 -0
- package/src/book-components/BookEditor/BookEditorActionbar.tsx +3 -3
- package/src/cli/cli-commands/agent/agentCliOptions.ts +63 -0
- package/src/cli/cli-commands/agent/chat.ts +54 -0
- package/src/cli/cli-commands/agent/exec.ts +60 -0
- package/src/cli/cli-commands/agent.ts +45 -0
- package/src/cli/cli-commands/agents-server/startAgentsServer.ts +3 -19
- package/src/cli/cli-commands/coder/getDefaultCoderPackageJsonScripts.ts +1 -1
- package/src/cli/cli-commands/common/promptRunnerCliOptions.ts +27 -23
- package/src/cli/promptbookCli.ts +2 -0
- package/src/other/templates/getTemplatesPipelineCollection.ts +836 -774
- package/src/version.ts +2 -2
- package/src/versions.txt +1 -0
- package/umd/index.umd.js +9325 -8883
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-agent-chat/executeAgentChatTurn.d.ts +28 -0
- package/umd/scripts/run-agent-chat/runAgentChat.d.ts +5 -0
- package/umd/scripts/run-agent-chat/runAgentExec.d.ts +11 -0
- package/umd/scripts/run-agent-messages/messages/createAgentRunnerSystemMessage.d.ts +10 -0
- package/umd/scripts/run-codex-prompts/common/resolveInlineOrFileText.d.ts +14 -0
- package/umd/src/_packages/node.index.d.ts +20 -0
- package/umd/src/_packages/types.index.d.ts +16 -0
- package/umd/src/book-3.0/BookNodeAgentSource.d.ts +38 -0
- package/umd/src/book-3.0/CliAgent.d.ts +68 -0
- package/umd/src/book-3.0/CliAgent.test.d.ts +1 -0
- package/umd/src/book-3.0/LiteAgent.d.ts +68 -0
- package/umd/src/book-3.0/LiteAgent.test.d.ts +1 -0
- package/umd/src/book-components/BookEditor/BookEditorAboutPromptbookInformation.d.ts +12 -0
- package/umd/src/cli/cli-commands/agent/agentCliOptions.d.ts +29 -0
- package/umd/src/cli/cli-commands/agent/chat.d.ts +10 -0
- package/umd/src/cli/cli-commands/agent/exec.d.ts +10 -0
- package/umd/src/cli/cli-commands/agent/run.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/agent.d.ts +14 -0
- package/umd/src/cli/cli-commands/agents-server/startAgentsServer.d.ts +3 -4
- package/umd/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +9 -9
- package/umd/src/version.d.ts +1 -1
- /package/esm/src/{cli/cli-commands/agents-server/startAgentsServer.test.d.ts → book-3.0/CliAgent.test.d.ts} +0 -0
- /package/{umd/src/cli/cli-commands/agents-server/startAgentsServer.test.d.ts → esm/src/book-3.0/LiteAgent.test.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -561,11 +561,11 @@ npx ts-node ./src/cli/test/ptbk.ts coder generate-boilerplates --template prompt
|
|
|
561
561
|
|
|
562
562
|
npx ts-node ./src/cli/test/ptbk.ts coder generate-boilerplates --template prompts/templates/agents-server.md
|
|
563
563
|
|
|
564
|
-
npx ts-node ./src/cli/test/ptbk.ts coder run --
|
|
564
|
+
npx ts-node ./src/cli/test/ptbk.ts coder run --harness github-copilot --model gpt-5.4 --thinking-level xhigh --context AGENTS.md
|
|
565
565
|
|
|
566
|
-
npx ts-node ./src/cli/test/ptbk.ts coder run --
|
|
566
|
+
npx ts-node ./src/cli/test/ptbk.ts coder run --harness github-copilot --model gpt-5.4 --thinking-level xhigh --context AGENTS.md --auto-push
|
|
567
567
|
|
|
568
|
-
npx ts-node ./src/cli/test/ptbk.ts coder run --
|
|
568
|
+
npx ts-node ./src/cli/test/ptbk.ts coder run --harness github-copilot --model gpt-5.4 --thinking-level xhigh --context AGENTS.md --ignore-git-changes --no-wait
|
|
569
569
|
|
|
570
570
|
npx ts-node ./src/cli/test/ptbk.ts coder find-refactor-candidates
|
|
571
571
|
|
|
@@ -587,11 +587,11 @@ ptbk coder generate-boilerplates
|
|
|
587
587
|
|
|
588
588
|
ptbk coder generate-boilerplates --template prompts/templates/common.md
|
|
589
589
|
|
|
590
|
-
ptbk coder run --
|
|
590
|
+
ptbk coder run --harness github-copilot --model gpt-5.4 --thinking-level xhigh --context AGENTS.md --test npm run test
|
|
591
591
|
|
|
592
|
-
ptbk coder run --
|
|
592
|
+
ptbk coder run --harness github-copilot --model gpt-5.4 --thinking-level xhigh --context AGENTS.md --auto-push
|
|
593
593
|
|
|
594
|
-
ptbk coder run --
|
|
594
|
+
ptbk coder run --harness github-copilot --model gpt-5.4 --thinking-level xhigh --context AGENTS.md --test npm run test --ignore-git-changes --no-wait
|
|
595
595
|
|
|
596
596
|
ptbk coder find-refactor-candidates
|
|
597
597
|
|
|
@@ -616,7 +616,7 @@ ptbk coder verify
|
|
|
616
616
|
|
|
617
617
|
| Flag | Purpose |
|
|
618
618
|
| -------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
619
|
-
| `--
|
|
619
|
+
| `--harness <name>` | Selects the coding harness. |
|
|
620
620
|
| `--model <model>` | Chooses the runner model; required for `openai-codex` and `gemini`, optional for `github-copilot`. |
|
|
621
621
|
| `--context <text-or-file>` | Appends extra instructions inline or from a file like `AGENTS.md`. |
|
|
622
622
|
| `--test <command>` | Runs a verification command after each prompt attempt and feeds failing output back for retries. |
|
|
@@ -9,7 +9,7 @@ The installed CLI can initialize a local Agents Server project before it starts
|
|
|
9
9
|
```bash
|
|
10
10
|
npm install ptbk
|
|
11
11
|
ptbk agents-server init
|
|
12
|
-
ptbk agents-server start --
|
|
12
|
+
ptbk agents-server start --harness github-copilot --model gpt-5.4 --thinking-level xhigh
|
|
13
13
|
```
|
|
14
14
|
|
|
15
15
|
`ptbk agents-server init` adds missing placeholders to `.env` and local runtime exclusions to `.gitignore` without deleting existing configuration. Use `PTBK_AGENTS_SERVER_DATABASE=supabase` for a Supabase-backed server or `PTBK_AGENTS_SERVER_DATABASE=sqlite` for a standalone local database in `.promptbook`. When using Supabase, fill the initialized values from your project before starting the server. The Supabase project URL and API keys are available in the [Supabase project API settings](https://supabase.com/docs/guides/api/api-keys), and the PostgreSQL connection string is available from the [Supabase database connection guide](https://supabase.com/docs/guides/database/connecting-to-postgres).
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { withSentryConfig } from '@sentry/nextjs';
|
|
1
2
|
import type { NextConfig } from 'next';
|
|
2
3
|
import { readdirSync } from 'fs';
|
|
3
4
|
import path from 'path';
|
|
5
|
+
import { SENTRY_ORGANIZATION, SENTRY_PROJECT } from './src/utils/errorReporting/sentrySdkConfig';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* Next.js build output directory.
|
|
@@ -20,6 +22,11 @@ const agentsServerNodeModulesPath = process.env.PTBK_AGENTS_SERVER_NODE_MODULES_
|
|
|
20
22
|
*/
|
|
21
23
|
const isNextValidationIgnored = process.env.PTBK_AGENTS_SERVER_IGNORE_NEXT_VALIDATION === 'true';
|
|
22
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Whether Sentry source maps can be uploaded during production builds.
|
|
27
|
+
*/
|
|
28
|
+
const IS_SENTRY_SOURCE_MAP_UPLOAD_ENABLED = Boolean(process.env.SENTRY_AUTH_TOKEN);
|
|
29
|
+
|
|
23
30
|
/**
|
|
24
31
|
* Exact aliases for local generated Promptbook package entrypoints.
|
|
25
32
|
*/
|
|
@@ -122,7 +129,19 @@ const nextConfig: NextConfig = {
|
|
|
122
129
|
},
|
|
123
130
|
};
|
|
124
131
|
|
|
125
|
-
export default nextConfig
|
|
132
|
+
export default withSentryConfig(nextConfig, {
|
|
133
|
+
org: SENTRY_ORGANIZATION,
|
|
134
|
+
project: SENTRY_PROJECT,
|
|
135
|
+
silent: true,
|
|
136
|
+
sourcemaps: {
|
|
137
|
+
disable: !IS_SENTRY_SOURCE_MAP_UPLOAD_ENABLED,
|
|
138
|
+
},
|
|
139
|
+
webpack: {
|
|
140
|
+
treeshake: {
|
|
141
|
+
removeDebugLogging: true,
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
});
|
|
126
145
|
|
|
127
146
|
/**
|
|
128
147
|
* Creates webpack/Turbopack aliases from imports like `@promptbook-local/core` to generated local sources.
|
|
@@ -57,7 +57,7 @@ async function handleUserChatJobWorkerRequest(request: Request) {
|
|
|
57
57
|
|
|
58
58
|
after(() =>
|
|
59
59
|
triggerUserChatJobWorker({ origin }).catch((error) =>
|
|
60
|
-
console.
|
|
60
|
+
console.warn('[user-chat-job] requeue failed', error),
|
|
61
61
|
),
|
|
62
62
|
);
|
|
63
63
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as Sentry from '@sentry/nextjs';
|
|
2
|
+
import {
|
|
3
|
+
createSentrySdkTags,
|
|
4
|
+
resolveBrowserSentryDsn,
|
|
5
|
+
resolveSentrySdkEnvironment,
|
|
6
|
+
resolveSentrySdkRelease,
|
|
7
|
+
SENTRY_TRACE_PROPAGATION_TARGETS,
|
|
8
|
+
SENTRY_TRACES_SAMPLE_RATE,
|
|
9
|
+
} from './utils/errorReporting/sentrySdkConfig';
|
|
10
|
+
|
|
11
|
+
Sentry.init({
|
|
12
|
+
dsn: resolveBrowserSentryDsn(),
|
|
13
|
+
tracesSampleRate: SENTRY_TRACES_SAMPLE_RATE,
|
|
14
|
+
environment: resolveSentrySdkEnvironment(),
|
|
15
|
+
release: resolveSentrySdkRelease(),
|
|
16
|
+
integrations: [Sentry.browserTracingIntegration()],
|
|
17
|
+
tracePropagationTargets: SENTRY_TRACE_PROPAGATION_TARGETS,
|
|
18
|
+
initialScope: {
|
|
19
|
+
tags: createSentrySdkTags(),
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Reports app-router navigation spans to Sentry.
|
|
25
|
+
*
|
|
26
|
+
* @private Sentry hook for Next.js client navigation instrumentation
|
|
27
|
+
*/
|
|
28
|
+
export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as Sentry from '@sentry/nextjs';
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Registers startup hooks for the Agents Server runtime.
|
|
3
5
|
*
|
|
@@ -5,11 +7,18 @@
|
|
|
5
7
|
* @private internal startup hook for Agents Server runtime
|
|
6
8
|
*/
|
|
7
9
|
export async function register(): Promise<void> {
|
|
10
|
+
if (process.env.NEXT_RUNTIME === 'edge') {
|
|
11
|
+
await import('./sentry.edge.config');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
|
|
8
15
|
if (process.env.NEXT_RUNTIME !== 'nodejs') {
|
|
9
16
|
return;
|
|
10
17
|
}
|
|
11
18
|
|
|
12
19
|
try {
|
|
20
|
+
await import('./sentry.server.config');
|
|
21
|
+
|
|
13
22
|
const { registerServerErrorSentryLogging } = await import('./utils/errorReporting/registerServerErrorSentryLogging');
|
|
14
23
|
registerServerErrorSentryLogging();
|
|
15
24
|
|
|
@@ -25,3 +34,10 @@ export async function register(): Promise<void> {
|
|
|
25
34
|
});
|
|
26
35
|
}
|
|
27
36
|
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Reports request errors from the Next.js app router to Sentry.
|
|
40
|
+
*
|
|
41
|
+
* @private Sentry hook for Next.js request instrumentation
|
|
42
|
+
*/
|
|
43
|
+
export const onRequestError = Sentry.captureRequestError;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as Sentry from '@sentry/nextjs';
|
|
2
|
+
import {
|
|
3
|
+
createSentrySdkTags,
|
|
4
|
+
resolveBrowserSentryDsn,
|
|
5
|
+
resolveSentrySdkEnvironment,
|
|
6
|
+
resolveSentrySdkRelease,
|
|
7
|
+
SENTRY_TRACES_SAMPLE_RATE,
|
|
8
|
+
} from './utils/errorReporting/sentrySdkConfig';
|
|
9
|
+
|
|
10
|
+
Sentry.init({
|
|
11
|
+
dsn: resolveBrowserSentryDsn(),
|
|
12
|
+
tracesSampleRate: SENTRY_TRACES_SAMPLE_RATE,
|
|
13
|
+
environment: resolveSentrySdkEnvironment(),
|
|
14
|
+
release: resolveSentrySdkRelease(),
|
|
15
|
+
initialScope: {
|
|
16
|
+
tags: createSentrySdkTags(),
|
|
17
|
+
},
|
|
18
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as Sentry from '@sentry/nextjs';
|
|
2
|
+
import { createAgentsServerSentryContext } from './utils/errorReporting/agentsServerSentryContext';
|
|
3
|
+
import { resolveServerSentryDsn, SENTRY_TRACES_SAMPLE_RATE } from './utils/errorReporting/sentrySdkConfig';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Shared diagnostic context applied to server-side SDK events at initialization time.
|
|
7
|
+
*/
|
|
8
|
+
const agentsServerSentryContext = createAgentsServerSentryContext();
|
|
9
|
+
|
|
10
|
+
Sentry.init({
|
|
11
|
+
dsn: resolveServerSentryDsn(),
|
|
12
|
+
tracesSampleRate: SENTRY_TRACES_SAMPLE_RATE,
|
|
13
|
+
environment: agentsServerSentryContext.environment,
|
|
14
|
+
release: agentsServerSentryContext.release,
|
|
15
|
+
initialScope: {
|
|
16
|
+
tags: agentsServerSentryContext.tags,
|
|
17
|
+
extra: agentsServerSentryContext.extra,
|
|
18
|
+
},
|
|
19
|
+
});
|
|
@@ -37,7 +37,7 @@ export async function readConfiguredCodeRunner(): Promise<ConfiguredCodeRunner>
|
|
|
37
37
|
>;
|
|
38
38
|
|
|
39
39
|
return {
|
|
40
|
-
agent: environmentByKey.
|
|
40
|
+
agent: environmentByKey.PTBK_HARNESS || process.env.PTBK_HARNESS || process.env.PTBK_AGENT || 'github-copilot',
|
|
41
41
|
model: environmentByKey.PTBK_MODEL || process.env.PTBK_MODEL || 'gpt-5.4',
|
|
42
42
|
thinkingLevel: environmentByKey.PTBK_THINKING_LEVEL || process.env.PTBK_THINKING_LEVEL || 'xhigh',
|
|
43
43
|
};
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { BOOK_LANGUAGE_VERSION, PROMPTBOOK_ENGINE_VERSION } from '../../../../../src/version';
|
|
2
|
+
import {
|
|
3
|
+
createSentrySdkTags,
|
|
4
|
+
resolveSentrySdkCommitHash,
|
|
5
|
+
resolveSentrySdkEnvironment,
|
|
6
|
+
resolveSentrySdkRelease,
|
|
7
|
+
resolveSentrySdkRepositoryBranch,
|
|
8
|
+
} from './sentrySdkConfig';
|
|
9
|
+
import type { SentryStorePayload } from './sentryStore';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Shared deployment and runtime context added to every Agents Server Sentry event.
|
|
13
|
+
*/
|
|
14
|
+
type AgentsServerSentryContext = {
|
|
15
|
+
/**
|
|
16
|
+
* Sentry release identifier.
|
|
17
|
+
*/
|
|
18
|
+
readonly release: string;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Sentry environment identifier.
|
|
22
|
+
*/
|
|
23
|
+
readonly environment: string;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Filterable Sentry tags.
|
|
27
|
+
*/
|
|
28
|
+
readonly tags: Record<string, string>;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Full non-secret diagnostic context.
|
|
32
|
+
*/
|
|
33
|
+
readonly extra: Record<string, unknown>;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Adds shared Agents Server release, environment, version, deployment, git, and runtime details.
|
|
38
|
+
*
|
|
39
|
+
* @param payload - Event-specific Sentry payload.
|
|
40
|
+
* @returns Payload enriched with common Agents Server diagnostics.
|
|
41
|
+
*
|
|
42
|
+
* @private internal helper for Agents Server Sentry reporting
|
|
43
|
+
*/
|
|
44
|
+
export function enrichSentryStorePayloadWithAgentsServerContext(payload: SentryStorePayload): SentryStorePayload {
|
|
45
|
+
const context = createAgentsServerSentryContext();
|
|
46
|
+
|
|
47
|
+
return {
|
|
48
|
+
...payload,
|
|
49
|
+
release: context.release,
|
|
50
|
+
environment: context.environment,
|
|
51
|
+
tags: {
|
|
52
|
+
...context.tags,
|
|
53
|
+
...payload.tags,
|
|
54
|
+
},
|
|
55
|
+
extra: {
|
|
56
|
+
...context.extra,
|
|
57
|
+
...payload.extra,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Creates a current Agents Server diagnostic context matching the admin About page metadata.
|
|
64
|
+
*
|
|
65
|
+
* @returns Common Sentry context for one event.
|
|
66
|
+
*
|
|
67
|
+
* @private internal helper for Agents Server Sentry reporting
|
|
68
|
+
*/
|
|
69
|
+
export function createAgentsServerSentryContext(): AgentsServerSentryContext {
|
|
70
|
+
const deploymentEnvironment = resolveSentrySdkEnvironment();
|
|
71
|
+
const appPackageVersion = normalizeOptionalString(process.env.npm_package_version) ?? PROMPTBOOK_ENGINE_VERSION;
|
|
72
|
+
const commitHash = resolveSentrySdkCommitHash();
|
|
73
|
+
const repositoryBranch = resolveSentrySdkRepositoryBranch();
|
|
74
|
+
const memoryUsage = process.memoryUsage();
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
release: resolveSentrySdkRelease(),
|
|
78
|
+
environment: deploymentEnvironment,
|
|
79
|
+
tags: createSentrySdkTags(),
|
|
80
|
+
extra: {
|
|
81
|
+
agentsServer: {
|
|
82
|
+
versions: {
|
|
83
|
+
promptbookEngineVersion: PROMPTBOOK_ENGINE_VERSION,
|
|
84
|
+
bookLanguageVersion: BOOK_LANGUAGE_VERSION,
|
|
85
|
+
appPackageVersion,
|
|
86
|
+
appPackageName: normalizeOptionalString(process.env.npm_package_name),
|
|
87
|
+
nextBuildId: normalizeOptionalString(process.env.NEXT_BUILD_ID),
|
|
88
|
+
nextDistDirectory: normalizeOptionalString(process.env.NEXT_DIST_DIR),
|
|
89
|
+
npmLifecycleEvent: normalizeOptionalString(process.env.npm_lifecycle_event),
|
|
90
|
+
npmUserAgent: normalizeOptionalString(process.env.npm_config_user_agent),
|
|
91
|
+
},
|
|
92
|
+
deployment: {
|
|
93
|
+
environment: deploymentEnvironment,
|
|
94
|
+
vercelEnvironment: getFirstNonEmptyString(process.env.NEXT_PUBLIC_VERCEL_ENV, process.env.VERCEL_ENV),
|
|
95
|
+
targetEnvironment: getFirstNonEmptyString(
|
|
96
|
+
process.env.NEXT_PUBLIC_VERCEL_TARGET_ENV,
|
|
97
|
+
process.env.VERCEL_TARGET_ENV,
|
|
98
|
+
),
|
|
99
|
+
siteUrl: normalizeOptionalString(process.env.NEXT_PUBLIC_SITE_URL),
|
|
100
|
+
vercelUrl: getFirstNonEmptyString(process.env.NEXT_PUBLIC_VERCEL_URL, process.env.VERCEL_URL),
|
|
101
|
+
vercelBranchUrl: normalizeOptionalString(process.env.NEXT_PUBLIC_VERCEL_BRANCH_URL),
|
|
102
|
+
vercelProductionUrl: normalizeOptionalString(process.env.NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL),
|
|
103
|
+
vercelRegion: normalizeOptionalString(process.env.VERCEL_REGION),
|
|
104
|
+
repositoryRef: normalizeOptionalString(process.env.PROMPTBOOK_REPOSITORY_REF),
|
|
105
|
+
supabaseTablePrefix: normalizeOptionalString(process.env.SUPABASE_TABLE_PREFIX),
|
|
106
|
+
currentWorkingDirectory: process.cwd(),
|
|
107
|
+
},
|
|
108
|
+
git: {
|
|
109
|
+
provider: getFirstNonEmptyString(
|
|
110
|
+
process.env.NEXT_PUBLIC_VERCEL_GIT_PROVIDER,
|
|
111
|
+
process.env.VERCEL_GIT_PROVIDER,
|
|
112
|
+
),
|
|
113
|
+
repositoryOwner: getFirstNonEmptyString(
|
|
114
|
+
process.env.NEXT_PUBLIC_VERCEL_GIT_REPO_OWNER,
|
|
115
|
+
process.env.VERCEL_GIT_REPO_OWNER,
|
|
116
|
+
),
|
|
117
|
+
repositorySlug: getFirstNonEmptyString(
|
|
118
|
+
process.env.NEXT_PUBLIC_VERCEL_GIT_REPO_SLUG,
|
|
119
|
+
process.env.VERCEL_GIT_REPO_SLUG,
|
|
120
|
+
),
|
|
121
|
+
repositoryId: getFirstNonEmptyString(
|
|
122
|
+
process.env.NEXT_PUBLIC_VERCEL_GIT_REPO_ID,
|
|
123
|
+
process.env.VERCEL_GIT_REPO_ID,
|
|
124
|
+
),
|
|
125
|
+
commitHash,
|
|
126
|
+
previousCommitHash: getFirstNonEmptyString(
|
|
127
|
+
process.env.NEXT_PUBLIC_VERCEL_GIT_PREVIOUS_SHA,
|
|
128
|
+
process.env.VERCEL_GIT_PREVIOUS_SHA,
|
|
129
|
+
),
|
|
130
|
+
branch: repositoryBranch,
|
|
131
|
+
commitMessage: getFirstNonEmptyString(
|
|
132
|
+
process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_MESSAGE,
|
|
133
|
+
process.env.VERCEL_GIT_COMMIT_MESSAGE,
|
|
134
|
+
),
|
|
135
|
+
authorName: getFirstNonEmptyString(
|
|
136
|
+
process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_NAME,
|
|
137
|
+
process.env.VERCEL_GIT_COMMIT_AUTHOR_NAME,
|
|
138
|
+
),
|
|
139
|
+
authorLogin: getFirstNonEmptyString(
|
|
140
|
+
process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_AUTHOR_LOGIN,
|
|
141
|
+
process.env.VERCEL_GIT_COMMIT_AUTHOR_LOGIN,
|
|
142
|
+
),
|
|
143
|
+
pullRequestId: getFirstNonEmptyString(
|
|
144
|
+
process.env.NEXT_PUBLIC_VERCEL_GIT_PULL_REQUEST_ID,
|
|
145
|
+
process.env.VERCEL_GIT_PULL_REQUEST_ID,
|
|
146
|
+
),
|
|
147
|
+
},
|
|
148
|
+
runtime: {
|
|
149
|
+
nodeVersion: process.version,
|
|
150
|
+
nodeEnvironment: normalizeOptionalString(process.env.NODE_ENV),
|
|
151
|
+
nextRuntime: normalizeOptionalString(process.env.NEXT_RUNTIME),
|
|
152
|
+
processId: process.pid,
|
|
153
|
+
processUptimeSeconds: process.uptime(),
|
|
154
|
+
hostname: getFirstNonEmptyString(process.env.HOSTNAME, process.env.COMPUTERNAME),
|
|
155
|
+
platform: process.platform,
|
|
156
|
+
architecture: process.arch,
|
|
157
|
+
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC',
|
|
158
|
+
},
|
|
159
|
+
memory: {
|
|
160
|
+
rssBytes: memoryUsage.rss,
|
|
161
|
+
heapUsedBytes: memoryUsage.heapUsed,
|
|
162
|
+
heapTotalBytes: memoryUsage.heapTotal,
|
|
163
|
+
externalBytes: memoryUsage.external,
|
|
164
|
+
arrayBuffersBytes: memoryUsage.arrayBuffers ?? 0,
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Returns the first non-empty string from a list.
|
|
173
|
+
*
|
|
174
|
+
* @param values - Candidate values in priority order.
|
|
175
|
+
* @returns First trimmed string or null.
|
|
176
|
+
*/
|
|
177
|
+
function getFirstNonEmptyString(...values: Array<string | null | undefined>): string | null {
|
|
178
|
+
for (const value of values) {
|
|
179
|
+
const normalizedValue = normalizeOptionalString(value);
|
|
180
|
+
|
|
181
|
+
if (normalizedValue) {
|
|
182
|
+
return normalizedValue;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Trims one optional environment value.
|
|
191
|
+
*
|
|
192
|
+
* @param value - Raw optional value.
|
|
193
|
+
* @returns Trimmed string or null.
|
|
194
|
+
*/
|
|
195
|
+
function normalizeOptionalString(value: string | null | undefined): string | null {
|
|
196
|
+
if (typeof value !== 'string') {
|
|
197
|
+
return null;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const normalizedValue = value.trim();
|
|
201
|
+
|
|
202
|
+
return normalizedValue || null;
|
|
203
|
+
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { inspect } from 'node:util';
|
|
2
|
+
import * as Sentry from '@sentry/nextjs';
|
|
2
3
|
import { DEFAULT_APPLICATION_ERROR_SERVER_NAME } from './applicationErrorHandling';
|
|
4
|
+
import { createAgentsServerSentryContext } from './agentsServerSentryContext';
|
|
5
|
+
import { enrichSentryStorePayloadWithAgentsServerContext } from './agentsServerSentryContext';
|
|
3
6
|
import {
|
|
4
7
|
createSentryTimestamp,
|
|
5
8
|
resolveOptionalSentryDsn,
|
|
@@ -81,13 +84,17 @@ export function registerServerErrorSentryLogging(): void {
|
|
|
81
84
|
console.error = (...consoleArguments: unknown[]): void => {
|
|
82
85
|
loggingState.originalConsoleError?.(...consoleArguments);
|
|
83
86
|
|
|
87
|
+
const sentryPayload = createServerErrorSentryStorePayload(consoleArguments);
|
|
88
|
+
|
|
89
|
+
if (captureServerErrorWithSentrySdk(sentryPayload)) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
|
|
84
93
|
const sentryDsn = resolveOptionalSentryDsn();
|
|
85
94
|
if (!sentryDsn) {
|
|
86
95
|
return;
|
|
87
96
|
}
|
|
88
97
|
|
|
89
|
-
const sentryPayload = createServerErrorSentryStorePayload(consoleArguments);
|
|
90
|
-
|
|
91
98
|
// Never log reporting failures through `console.error`, otherwise a broken Sentry configuration would recurse.
|
|
92
99
|
void sendSentryStorePayload(sentryPayload, sentryDsn).catch(() => undefined);
|
|
93
100
|
};
|
|
@@ -144,7 +151,7 @@ function getServerErrorSentryLoggingState(): ServerErrorSentryLoggingState {
|
|
|
144
151
|
function createServerErrorSentryStorePayload(consoleArguments: readonly unknown[]): SentryStorePayload {
|
|
145
152
|
const loggedError = findLoggedErrorInfo(consoleArguments);
|
|
146
153
|
|
|
147
|
-
return {
|
|
154
|
+
return enrichSentryStorePayloadWithAgentsServerContext({
|
|
148
155
|
platform: 'javascript',
|
|
149
156
|
level: 'error',
|
|
150
157
|
logger: SENTRY_SERVER_ERROR_LOGGER,
|
|
@@ -153,8 +160,6 @@ function createServerErrorSentryStorePayload(consoleArguments: readonly unknown[
|
|
|
153
160
|
server_name: process.env.NEXT_PUBLIC_SERVER_NAME ?? DEFAULT_APPLICATION_ERROR_SERVER_NAME,
|
|
154
161
|
tags: {
|
|
155
162
|
source: 'agents-server.console-error',
|
|
156
|
-
nextRuntime: process.env.NEXT_RUNTIME ?? 'nodejs',
|
|
157
|
-
nodeEnv: process.env.NODE_ENV ?? 'unknown',
|
|
158
163
|
},
|
|
159
164
|
exception: loggedError
|
|
160
165
|
? {
|
|
@@ -169,11 +174,56 @@ function createServerErrorSentryStorePayload(consoleArguments: readonly unknown[
|
|
|
169
174
|
extra: {
|
|
170
175
|
consoleArguments: consoleArguments.map(serializeConsoleArgument),
|
|
171
176
|
errorStack: loggedError?.stack ?? null,
|
|
172
|
-
vercelEnv: process.env.VERCEL_ENV ?? null,
|
|
173
|
-
vercelRegion: process.env.VERCEL_REGION ?? null,
|
|
174
|
-
vercelUrl: process.env.VERCEL_URL ?? null,
|
|
175
177
|
},
|
|
176
|
-
};
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Captures a server-side console error through the official Sentry SDK when it is initialized.
|
|
183
|
+
*
|
|
184
|
+
* @param sentryPayload - Structured event payload created from the original `console.error` call.
|
|
185
|
+
* @returns True when the SDK accepted the event.
|
|
186
|
+
*/
|
|
187
|
+
function captureServerErrorWithSentrySdk(sentryPayload: SentryStorePayload): boolean {
|
|
188
|
+
if (!Sentry.getClient()) {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const agentsServerContext = createAgentsServerSentryContext();
|
|
193
|
+
|
|
194
|
+
Sentry.captureException(createServerErrorSdkException(sentryPayload), {
|
|
195
|
+
level: sentryPayload.level,
|
|
196
|
+
tags: {
|
|
197
|
+
...agentsServerContext.tags,
|
|
198
|
+
...sentryPayload.tags,
|
|
199
|
+
},
|
|
200
|
+
extra: {
|
|
201
|
+
...agentsServerContext.extra,
|
|
202
|
+
...sentryPayload.extra,
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Rebuilds an `Error` object from the structured Sentry payload so the SDK can parse stack frames.
|
|
211
|
+
*
|
|
212
|
+
* @param sentryPayload - Structured event payload created from the original `console.error` call.
|
|
213
|
+
* @returns Error object with the original stack when one was logged.
|
|
214
|
+
*/
|
|
215
|
+
function createServerErrorSdkException(sentryPayload: SentryStorePayload): Error {
|
|
216
|
+
const error = new Error(sentryPayload.message);
|
|
217
|
+
const exceptionValue = sentryPayload.exception?.values.at(0);
|
|
218
|
+
const errorStack = sentryPayload.extra?.errorStack;
|
|
219
|
+
|
|
220
|
+
error.name = exceptionValue?.type ?? 'Error';
|
|
221
|
+
|
|
222
|
+
if (typeof errorStack === 'string' && errorStack.trim()) {
|
|
223
|
+
error.stack = errorStack;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return error;
|
|
177
227
|
}
|
|
178
228
|
|
|
179
229
|
/**
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import * as Sentry from '@sentry/nextjs';
|
|
1
2
|
import type { ApplicationErrorReportPayload } from './applicationErrorHandling';
|
|
3
|
+
import { enrichSentryStorePayloadWithAgentsServerContext } from './agentsServerSentryContext';
|
|
2
4
|
import {
|
|
3
5
|
createSentryTimestamp,
|
|
4
6
|
resolveRequiredSentryDsn,
|
|
@@ -18,7 +20,7 @@ const SENTRY_APPLICATION_ERROR_LOGGER = 'agents-server.application-error';
|
|
|
18
20
|
* @returns Sentry store payload.
|
|
19
21
|
*/
|
|
20
22
|
function createSentryStorePayload(report: ApplicationErrorReportPayload): SentryStorePayload {
|
|
21
|
-
return {
|
|
23
|
+
return enrichSentryStorePayloadWithAgentsServerContext({
|
|
22
24
|
platform: 'javascript',
|
|
23
25
|
level: 'error',
|
|
24
26
|
logger: SENTRY_APPLICATION_ERROR_LOGGER,
|
|
@@ -44,7 +46,7 @@ function createSentryStorePayload(report: ApplicationErrorReportPayload): Sentry
|
|
|
44
46
|
pageUrl: report.pageUrl ?? null,
|
|
45
47
|
reportedAt: report.reportedAt,
|
|
46
48
|
},
|
|
47
|
-
};
|
|
49
|
+
});
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
/**
|
|
@@ -53,5 +55,39 @@ function createSentryStorePayload(report: ApplicationErrorReportPayload): Sentry
|
|
|
53
55
|
* @param report - Structured browser report payload.
|
|
54
56
|
*/
|
|
55
57
|
export async function sendApplicationErrorReportToSentry(report: ApplicationErrorReportPayload): Promise<void> {
|
|
56
|
-
|
|
58
|
+
const sentryPayload = createSentryStorePayload(report);
|
|
59
|
+
|
|
60
|
+
if (Sentry.getClient()) {
|
|
61
|
+
Sentry.captureException(createApplicationErrorSdkException(report, sentryPayload), {
|
|
62
|
+
level: sentryPayload.level,
|
|
63
|
+
tags: sentryPayload.tags,
|
|
64
|
+
extra: sentryPayload.extra,
|
|
65
|
+
});
|
|
66
|
+
await Sentry.flush(2000);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
await sendSentryStorePayload(sentryPayload, resolveRequiredSentryDsn());
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Rebuilds an `Error` object from a browser application report so the SDK can parse stack frames.
|
|
75
|
+
*
|
|
76
|
+
* @param report - Browser-generated application error report.
|
|
77
|
+
* @param sentryPayload - Structured Sentry payload created from the report.
|
|
78
|
+
* @returns Error object with the original browser stack when available.
|
|
79
|
+
*/
|
|
80
|
+
function createApplicationErrorSdkException(
|
|
81
|
+
report: ApplicationErrorReportPayload,
|
|
82
|
+
sentryPayload: SentryStorePayload,
|
|
83
|
+
): Error {
|
|
84
|
+
const error = new Error(sentryPayload.message);
|
|
85
|
+
|
|
86
|
+
error.name = report.errorName || 'Error';
|
|
87
|
+
|
|
88
|
+
if (report.errorStack?.trim()) {
|
|
89
|
+
error.stack = report.errorStack;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return error;
|
|
57
93
|
}
|