@promptbook/cli 0.112.0-26 → 0.112.0-28

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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Git identity details that must drive commits created by the coding agent.
2
+ * Git identity details that drive commits created by the coding agent.
3
3
  */
4
4
  export type AgentGitIdentity = {
5
5
  readonly name: string;
@@ -7,14 +7,21 @@ export type AgentGitIdentity = {
7
7
  readonly signingKey: string;
8
8
  };
9
9
  /**
10
- * Reads the required agent identity values from the environment and remembers them for the lifetime of the script.
10
+ * Reads the optional agent identity values from the environment.
11
+ *
12
+ * Falls back to the user's default Git configuration whenever the dedicated coding-agent
13
+ * identity is only partially configured.
11
14
  */
12
- export declare function getAgentGitIdentity(): AgentGitIdentity;
15
+ export declare function getAgentGitIdentity(): AgentGitIdentity | undefined;
13
16
  /**
14
- * Builds the environment overrides that ensure git commits use the agent identity instead of the primary user.
17
+ * Builds the environment overrides that ensure git commits use the dedicated agent identity instead of the primary user.
15
18
  */
16
- export declare function buildAgentGitEnv(identity?: AgentGitIdentity): Record<string, string>;
19
+ export declare function buildAgentGitEnv(identity?: AgentGitIdentity | undefined): Record<string, string> | undefined;
17
20
  /**
18
21
  * Produces the git commit flag that enforces signing with the configured agent key.
19
22
  */
20
- export declare function buildAgentGitSigningFlag(identity?: AgentGitIdentity): string;
23
+ export declare function buildAgentGitSigningFlag(identity?: AgentGitIdentity | undefined): string | undefined;
24
+ /**
25
+ * Prints a one-time style tip when coding-agent commits fall back to the user's default Git configuration.
26
+ */
27
+ export declare function printAgentGitIdentityTipIfNeeded(): void;
@@ -1,4 +1,5 @@
1
1
  /**
2
- * Commits staged changes with the provided message using the configured agent identity and signing key.
2
+ * Commits staged changes with the provided message using the dedicated coding-agent identity when configured,
3
+ * otherwise falls back to the default Git configuration.
3
4
  */
4
5
  export declare function commitChanges(message: string): Promise<void>;
@@ -26,45 +26,6 @@ export type HoistedMenuItem = {
26
26
  */
27
27
  isActive?: boolean;
28
28
  };
29
- /**
30
- * Shared actions provided to hoisted mobile menu-section renderers.
31
- *
32
- * @private mechanism inside Promptbook
33
- */
34
- export type HoistedMobileMenuSectionRenderOptions = {
35
- /**
36
- * Closes the owning mobile header menu.
37
- */
38
- readonly closeMenu: () => void;
39
- };
40
- /**
41
- * Mobile-only section hoisted into the shared application menu.
42
- *
43
- * @private mechanism inside Promptbook
44
- */
45
- export type HoistedMobileMenuSection = {
46
- /**
47
- * Stable identifier used to preserve section open state.
48
- */
49
- readonly key: string;
50
- /**
51
- * Visible section label rendered by the mobile menu.
52
- */
53
- readonly label: ReactNode;
54
- /**
55
- * Whether the section should start expanded whenever the menu opens.
56
- */
57
- readonly isDefaultOpen?: boolean;
58
- /**
59
- * Lazily renders section content inside the mobile header menu.
60
- */
61
- readonly renderContent: (options: HoistedMobileMenuSectionRenderOptions) => ReactNode;
62
- };
63
- /**
64
- * Value exposed through the shared menu-hoisting context.
65
- *
66
- * @private mechanism inside Promptbook
67
- */
68
29
  type MenuHoistingContextType = {
69
30
  /**
70
31
  * The currently hoisted menu items
@@ -74,14 +35,6 @@ type MenuHoistingContextType = {
74
35
  * Set the hoisted menu items
75
36
  */
76
37
  setMenu: (items: HoistedMenuItem[]) => void;
77
- /**
78
- * Mobile-only sections hoisted into the shared application menu.
79
- */
80
- mobileMenuSections: HoistedMobileMenuSection[];
81
- /**
82
- * Sets the mobile-only hoisted menu sections.
83
- */
84
- setMobileMenuSections: (sections: HoistedMobileMenuSection[]) => void;
85
38
  };
86
39
  /**
87
40
  * Provider for menu hoisting
@@ -0,0 +1,30 @@
1
+ import type { AgentModelRequirements } from '../../book-2.0/agent-source/AgentModelRequirements';
2
+ import type { ParsedCommitment } from '../_base/ParsedCommitment';
3
+ /**
4
+ * `USE` commitment types whose system-message sections are aggregated after the
5
+ * commitment-by-commitment application step.
6
+ *
7
+ * @private internal utility of `createAgentModelRequirementsWithCommitments`
8
+ */
9
+ type AggregatedUseCommitmentType = 'USE BROWSER' | 'USE SEARCH ENGINE' | 'USE TIME';
10
+ /**
11
+ * Adds the placeholder for an aggregated `USE` system-message section only once, preserving the section position from the first occurrence.
12
+ *
13
+ * @param requirements - Current model requirements.
14
+ * @param type - Aggregated `USE` commitment type being applied.
15
+ * @returns Requirements with the placeholder inserted when it was not already present.
16
+ * @private internal utility of `USE` commitments
17
+ */
18
+ export declare function appendAggregatedUseCommitmentPlaceholder(requirements: AgentModelRequirements, type: AggregatedUseCommitmentType): AgentModelRequirements;
19
+ /**
20
+ * Replaces temporary `USE` placeholders with one aggregated system-message block per commitment type.
21
+ *
22
+ * Distinct additional-instruction blocks are merged in stable source order while the hard-coded section is emitted only once.
23
+ *
24
+ * @param requirements - Model requirements produced by commitment-by-commitment application.
25
+ * @param commitments - Filtered commitments in their original source order.
26
+ * @returns Requirements with aggregated `USE` system-message sections.
27
+ * @private internal utility of `createAgentModelRequirementsWithCommitments`
28
+ */
29
+ export declare function aggregateUseCommitmentSystemMessages(requirements: AgentModelRequirements, commitments: ReadonlyArray<ParsedCommitment>): AgentModelRequirements;
30
+ export {};
@@ -12,13 +12,14 @@ import { BaseCommitmentDefinition } from '../_base/BaseCommitmentDefinition';
12
12
  * 1. One-shot URL fetching: Simple function to fetch and scrape URL content
13
13
  * 2. Running browser: For complex tasks like scrolling, clicking, form filling, etc.
14
14
  *
15
- * The content following `USE BROWSER` is ignored (similar to NOTE).
15
+ * The content following `USE BROWSER` is an arbitrary text that the agent should know
16
+ * (e.g. browsing scope or preferred sources).
16
17
  *
17
18
  * Example usage in agent source:
18
19
  *
19
20
  * ```book
20
21
  * USE BROWSER
21
- * USE BROWSER This will be ignored
22
+ * USE BROWSER Prefer official documentation and source websites.
22
23
  * ```
23
24
  *
24
25
  * @private [🪔] Maybe export the commitments through some package
@@ -15,7 +15,7 @@ export declare const BOOK_LANGUAGE_VERSION: string_semantic_version;
15
15
  export declare const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version;
16
16
  /**
17
17
  * Represents the version string of the Promptbook engine.
18
- * It follows semantic versioning (e.g., `0.112.0-25`).
18
+ * It follows semantic versioning (e.g., `0.112.0-27`).
19
19
  *
20
20
  * @generated
21
21
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promptbook/cli",
3
- "version": "0.112.0-26",
3
+ "version": "0.112.0-28",
4
4
  "description": "Promptbook: Turn your company's scattered knowledge into AI ready books",
5
5
  "private": false,
6
6
  "sideEffects": false,
package/umd/index.umd.js CHANGED
@@ -60,7 +60,7 @@
60
60
  * @generated
61
61
  * @see https://github.com/webgptorg/promptbook
62
62
  */
63
- const PROMPTBOOK_ENGINE_VERSION = '0.112.0-26';
63
+ const PROMPTBOOK_ENGINE_VERSION = '0.112.0-28';
64
64
  /**
65
65
  * TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
66
66
  * Note: [💞] Ignore a discrepancy between file name and entity name
@@ -21902,6 +21902,147 @@
21902
21902
  * Note: [💞] Ignore a discrepancy between file name and entity name
21903
21903
  */
21904
21904
 
21905
+ /**
21906
+ * All `USE` commitment types currently participating in final system-message aggregation.
21907
+ *
21908
+ * @private internal constant for `aggregateUseCommitmentSystemMessages`
21909
+ */
21910
+ const AGGREGATED_USE_COMMITMENT_TYPES = ['USE BROWSER', 'USE SEARCH ENGINE', 'USE TIME'];
21911
+ /**
21912
+ * Prefix used for temporary in-system-message placeholders that preserve the first-occurrence position of aggregated `USE` sections.
21913
+ *
21914
+ * @private internal constant for `appendAggregatedUseCommitmentPlaceholder`
21915
+ */
21916
+ const AGGREGATED_USE_COMMITMENT_PLACEHOLDER_PREFIX = '# AGGREGATED USE COMMITMENT: ';
21917
+ /**
21918
+ * Type guard for `USE` commitment types that are aggregated in the final system message.
21919
+ *
21920
+ * @param type - Commitment type to check.
21921
+ * @returns `true` when the commitment participates in `USE` system-message aggregation.
21922
+ * @private internal utility of `aggregateUseCommitmentSystemMessages`
21923
+ */
21924
+ function isAggregatedUseCommitmentType(type) {
21925
+ return AGGREGATED_USE_COMMITMENT_TYPES.includes(type);
21926
+ }
21927
+ /**
21928
+ * Creates the placeholder token used to reserve the first-occurrence position of an aggregated `USE` system-message section.
21929
+ *
21930
+ * @param type - Aggregated `USE` commitment type.
21931
+ * @returns Single-line placeholder comment stored in the interim system message.
21932
+ * @private internal utility of `appendAggregatedUseCommitmentPlaceholder`
21933
+ */
21934
+ function getAggregatedUseCommitmentPlaceholder(type) {
21935
+ return `${AGGREGATED_USE_COMMITMENT_PLACEHOLDER_PREFIX}${type}`;
21936
+ }
21937
+ /**
21938
+ * Combines distinct additional instruction blocks in source order.
21939
+ *
21940
+ * @param additionalInstructions - Deduplicated instruction blocks collected from the agent source.
21941
+ * @returns Combined instruction text ready for `formatOptionalInstructionBlock`.
21942
+ * @private internal utility of `createAggregatedUseCommitmentSystemMessage`
21943
+ */
21944
+ function combineAdditionalInstructions(additionalInstructions) {
21945
+ return additionalInstructions.join('\n');
21946
+ }
21947
+ /**
21948
+ * Creates the final aggregated system-message section for a supported `USE` commitment type.
21949
+ *
21950
+ * @param type - Aggregated `USE` commitment type.
21951
+ * @param additionalInstructions - Distinct additional instructions in source order.
21952
+ * @returns Final system-message block for the commitment type.
21953
+ * @private internal utility of `aggregateUseCommitmentSystemMessages`
21954
+ */
21955
+ function createAggregatedUseCommitmentSystemMessage(type, additionalInstructions) {
21956
+ const combinedAdditionalInstructions = combineAdditionalInstructions(additionalInstructions);
21957
+ switch (type) {
21958
+ case 'USE TIME':
21959
+ return _spaceTrim.spaceTrim((block) => `
21960
+ Time and date context:
21961
+ - It is ${moment__default["default"]().format('MMMM YYYY')} now.
21962
+ - If you need more precise current time information, use the tool "get_current_time".
21963
+ ${block(formatOptionalInstructionBlock('Time instructions', combinedAdditionalInstructions))}
21964
+ `);
21965
+ case 'USE BROWSER':
21966
+ return _spaceTrim.spaceTrim((block) => `
21967
+ You have access to browser tools to fetch and access content from the internet.
21968
+ - Use "fetch_url_content" to retrieve content from specific URLs (webpages or documents) using scrapers.
21969
+ - Use "run_browser" for real interactive browser automation (navigation, clicks, typing, waiting, scrolling).
21970
+ When you need to know information from a specific website or document, use the fetch_url_content tool.
21971
+ ${block(formatOptionalInstructionBlock('Browser instructions', combinedAdditionalInstructions))}
21972
+ `);
21973
+ case 'USE SEARCH ENGINE':
21974
+ return _spaceTrim.spaceTrim((block) => `
21975
+ Tool:
21976
+ - You have access to the web search engine via the tool "web_search".
21977
+ - Use it to find up-to-date information or facts that you don't know.
21978
+ - When you need to know some information from the internet, use the tool provided to you.
21979
+ - Do not make up information when you can search for it.
21980
+ - Do not tell the user you cannot search for information, YOU CAN.
21981
+ ${block(formatOptionalInstructionBlock('Search instructions', combinedAdditionalInstructions))}
21982
+ `);
21983
+ }
21984
+ }
21985
+ /**
21986
+ * Adds the placeholder for an aggregated `USE` system-message section only once, preserving the section position from the first occurrence.
21987
+ *
21988
+ * @param requirements - Current model requirements.
21989
+ * @param type - Aggregated `USE` commitment type being applied.
21990
+ * @returns Requirements with the placeholder inserted when it was not already present.
21991
+ * @private internal utility of `USE` commitments
21992
+ */
21993
+ function appendAggregatedUseCommitmentPlaceholder(requirements, type) {
21994
+ const placeholder = getAggregatedUseCommitmentPlaceholder(type);
21995
+ if (requirements.systemMessage.includes(placeholder)) {
21996
+ return requirements;
21997
+ }
21998
+ const systemMessage = requirements.systemMessage.trim()
21999
+ ? `${requirements.systemMessage}\n\n${placeholder}`
22000
+ : placeholder;
22001
+ return {
22002
+ ...requirements,
22003
+ systemMessage,
22004
+ };
22005
+ }
22006
+ /**
22007
+ * Replaces temporary `USE` placeholders with one aggregated system-message block per commitment type.
22008
+ *
22009
+ * Distinct additional-instruction blocks are merged in stable source order while the hard-coded section is emitted only once.
22010
+ *
22011
+ * @param requirements - Model requirements produced by commitment-by-commitment application.
22012
+ * @param commitments - Filtered commitments in their original source order.
22013
+ * @returns Requirements with aggregated `USE` system-message sections.
22014
+ * @private internal utility of `createAgentModelRequirementsWithCommitments`
22015
+ */
22016
+ function aggregateUseCommitmentSystemMessages(requirements, commitments) {
22017
+ const additionalInstructionsByType = new Map();
22018
+ for (const commitment of commitments) {
22019
+ if (!isAggregatedUseCommitmentType(commitment.type)) {
22020
+ continue;
22021
+ }
22022
+ let additionalInstructions = additionalInstructionsByType.get(commitment.type);
22023
+ if (!additionalInstructions) {
22024
+ additionalInstructions = [];
22025
+ additionalInstructionsByType.set(commitment.type, additionalInstructions);
22026
+ }
22027
+ const normalizedContent = _spaceTrim.spaceTrim(commitment.content);
22028
+ if (normalizedContent && !additionalInstructions.includes(normalizedContent)) {
22029
+ additionalInstructions.push(normalizedContent);
22030
+ }
22031
+ }
22032
+ let systemMessage = requirements.systemMessage;
22033
+ for (const [type, additionalInstructions] of additionalInstructionsByType) {
22034
+ const placeholder = getAggregatedUseCommitmentPlaceholder(type);
22035
+ if (!systemMessage.includes(placeholder)) {
22036
+ continue;
22037
+ }
22038
+ systemMessage = systemMessage.replace(placeholder, createAggregatedUseCommitmentSystemMessage(type, additionalInstructions));
22039
+ }
22040
+ return {
22041
+ ...requirements,
22042
+ systemMessage,
22043
+ };
22044
+ }
22045
+
21905
22046
  /**
21906
22047
  * Client-side safe wrapper for fetching URL content
21907
22048
  *
@@ -21952,13 +22093,14 @@
21952
22093
  * 1. One-shot URL fetching: Simple function to fetch and scrape URL content
21953
22094
  * 2. Running browser: For complex tasks like scrolling, clicking, form filling, etc.
21954
22095
  *
21955
- * The content following `USE BROWSER` is ignored (similar to NOTE).
22096
+ * The content following `USE BROWSER` is an arbitrary text that the agent should know
22097
+ * (e.g. browsing scope or preferred sources).
21956
22098
  *
21957
22099
  * Example usage in agent source:
21958
22100
  *
21959
22101
  * ```book
21960
22102
  * USE BROWSER
21961
- * USE BROWSER This will be ignored
22103
+ * USE BROWSER Prefer official documentation and source websites.
21962
22104
  * ```
21963
22105
  *
21964
22106
  * @private [🪔] Maybe export the commitments through some package
@@ -21996,7 +22138,7 @@
21996
22138
 
21997
22139
  ## Key aspects
21998
22140
 
21999
- - The content following \`USE BROWSER\` is ignored (similar to NOTE)
22141
+ - The content following \`USE BROWSER\` is an arbitrary text that the agent should know (e.g. browsing scope or preferred sources).
22000
22142
  - Provides two levels of browser access:
22001
22143
  1. **One-shot URL fetching**: Simple function to fetch and scrape URL content (active)
22002
22144
  2. **Running browser**: For complex tasks like scrolling, clicking, form filling, etc. (runtime-dependent)
@@ -22113,20 +22255,14 @@
22113
22255
  });
22114
22256
  }
22115
22257
  const updatedTools = [...existingTools, ...toolsToAdd];
22116
- // Return requirements with updated tools and metadata
22117
- return this.appendToSystemMessage({
22258
+ return appendAggregatedUseCommitmentPlaceholder({
22118
22259
  ...requirements,
22119
22260
  tools: updatedTools,
22120
22261
  _metadata: {
22121
22262
  ...requirements._metadata,
22122
22263
  useBrowser: true,
22123
22264
  },
22124
- }, _spaceTrim.spaceTrim(`
22125
- You have access to browser tools to fetch and access content from the internet.
22126
- - Use "fetch_url_content" to retrieve content from specific URLs (webpages or documents) using scrapers.
22127
- - Use "run_browser" for real interactive browser automation (navigation, clicks, typing, waiting, scrolling).
22128
- When you need to know information from a specific website or document, use the fetch_url_content tool.
22129
- `));
22265
+ }, this.type);
22130
22266
  }
22131
22267
  /**
22132
22268
  * Gets the browser tool function implementations.
@@ -25913,7 +26049,6 @@
25913
26049
  `);
25914
26050
  }
25915
26051
  applyToAgentModelRequirements(requirements, content) {
25916
- const extraInstructions = formatOptionalInstructionBlock('Search instructions', content);
25917
26052
  // Get existing tools array or create new one
25918
26053
  const existingTools = requirements.tools || [];
25919
26054
  // Add 'web_search' to tools if not already present
@@ -25926,7 +26061,6 @@
25926
26061
  description: _spaceTrim.spaceTrim(`
25927
26062
  Search the internet for information.
25928
26063
  Use this tool when you need to find up-to-date information or facts that you don't know.
25929
- ${!content ? '' : `Search scope / instructions: ${content}`}
25930
26064
  `),
25931
26065
  parameters: {
25932
26066
  type: 'object',
@@ -25964,23 +26098,14 @@
25964
26098
  },
25965
26099
  },
25966
26100
  ];
25967
- // Return requirements with updated tools and metadata
25968
- return this.appendToSystemMessage({
26101
+ return appendAggregatedUseCommitmentPlaceholder({
25969
26102
  ...requirements,
25970
26103
  tools: updatedTools,
25971
26104
  _metadata: {
25972
26105
  ...requirements._metadata,
25973
26106
  useSearchEngine: content || true,
25974
26107
  },
25975
- }, _spaceTrim.spaceTrim((block) => `
25976
- Tool:
25977
- - You have access to the web search engine via the tool "web_search".
25978
- - Use it to find up-to-date information or facts that you don't know.
25979
- - When you need to know some information from the internet, use the tool provided to you.
25980
- - Do not make up information when you can search for it.
25981
- - Do not tell the user you cannot search for information, YOU CAN.
25982
- ${block(extraInstructions)}
25983
- `));
26108
+ }, this.type);
25984
26109
  }
25985
26110
  /**
25986
26111
  * Gets human-readable titles for tool functions provided by this commitment.
@@ -27091,7 +27216,6 @@
27091
27216
  `);
27092
27217
  }
27093
27218
  applyToAgentModelRequirements(requirements, content) {
27094
- const extraInstructions = formatOptionalInstructionBlock('Time instructions', content);
27095
27219
  // Get existing tools array or create new one
27096
27220
  const existingTools = requirements.tools || [];
27097
27221
  // Add 'get_current_time' to tools if not already present
@@ -27115,19 +27239,13 @@
27115
27239
  },
27116
27240
  // <- TODO: !!!! define the function in LLM tools
27117
27241
  ];
27118
- // Return requirements with updated tools and metadata
27119
- return this.appendToSystemMessage({
27242
+ return appendAggregatedUseCommitmentPlaceholder({
27120
27243
  ...requirements,
27121
27244
  tools: updatedTools,
27122
27245
  _metadata: {
27123
27246
  ...requirements._metadata,
27124
27247
  },
27125
- }, _spaceTrim.spaceTrim((block) => `
27126
- Time and date context:
27127
- - It is ${moment__default["default"]().format('MMMM YYYY')} now.
27128
- - If you need more precise current time information, use the tool "get_current_time".
27129
- ${block(extraInstructions)}
27130
- `));
27248
+ }, this.type);
27131
27249
  }
27132
27250
  /**
27133
27251
  * Gets human-readable titles for tool functions provided by this commitment.
@@ -39077,6 +39195,7 @@
39077
39195
  }
39078
39196
  }
39079
39197
  }
39198
+ requirements = aggregateUseCommitmentSystemMessages(requirements, filteredCommitments);
39080
39199
  // Handle IMPORT commitments for generic files
39081
39200
  // Note: This logic could be moved to ImportCommitmentDefinition, but it needs to be asynchronous
39082
39201
  if (requirements.importedFileUrls && requirements.importedFileUrls.length > 0) {
@@ -41437,24 +41556,36 @@
41437
41556
  * Environment variable that configures the signing key used for agent commits.
41438
41557
  */
41439
41558
  const AGENT_GIT_SIGNING_KEY_ENV = 'CODING_AGENT_GIT_SIGNING_KEY';
41440
- let cachedIdentity;
41441
41559
  /**
41442
- * Reads the required agent identity values from the environment and remembers them for the lifetime of the script.
41560
+ * Legacy environment variable that can also provide the signing key used for agent commits.
41561
+ */
41562
+ const AGENT_GPG_KEY_ID_ENV = 'CODING_AGENT_GPG_KEY_ID';
41563
+ /**
41564
+ * Environment variables accepted for the coding-agent Git signing key.
41565
+ */
41566
+ const AGENT_GIT_SIGNING_KEY_ENV_ALIASES = [AGENT_GIT_SIGNING_KEY_ENV, AGENT_GPG_KEY_ID_ENV];
41567
+ /**
41568
+ * Reads the optional agent identity values from the environment.
41569
+ *
41570
+ * Falls back to the user's default Git configuration whenever the dedicated coding-agent
41571
+ * identity is only partially configured.
41443
41572
  */
41444
41573
  function getAgentGitIdentity() {
41445
- if (cachedIdentity) {
41446
- return cachedIdentity;
41574
+ const name = readOptionalEnvValue(AGENT_GIT_NAME_ENV);
41575
+ const email = readOptionalEnvValue(AGENT_GIT_EMAIL_ENV);
41576
+ const signingKey = readOptionalSigningKeyValue();
41577
+ if (!name || !email || !signingKey) {
41578
+ return undefined;
41447
41579
  }
41448
- const name = readRequiredEnvValue(AGENT_GIT_NAME_ENV);
41449
- const email = readRequiredEnvValue(AGENT_GIT_EMAIL_ENV);
41450
- const signingKey = readRequiredEnvValue(AGENT_GIT_SIGNING_KEY_ENV);
41451
- cachedIdentity = { name, email, signingKey };
41452
- return cachedIdentity;
41580
+ return { name, email, signingKey };
41453
41581
  }
41454
41582
  /**
41455
- * Builds the environment overrides that ensure git commits use the agent identity instead of the primary user.
41583
+ * Builds the environment overrides that ensure git commits use the dedicated agent identity instead of the primary user.
41456
41584
  */
41457
41585
  function buildAgentGitEnv(identity = getAgentGitIdentity()) {
41586
+ if (!identity) {
41587
+ return undefined;
41588
+ }
41458
41589
  return {
41459
41590
  GIT_AUTHOR_NAME: identity.name,
41460
41591
  GIT_AUTHOR_EMAIL: identity.email,
@@ -41466,24 +41597,47 @@
41466
41597
  * Produces the git commit flag that enforces signing with the configured agent key.
41467
41598
  */
41468
41599
  function buildAgentGitSigningFlag(identity = getAgentGitIdentity()) {
41600
+ if (!identity) {
41601
+ return undefined;
41602
+ }
41469
41603
  return `--gpg-sign="${identity.signingKey}"`;
41470
41604
  }
41471
41605
  /**
41472
- * Reads a required environment variable and fails fast with a helpful message if it is missing.
41606
+ * Prints a one-time style tip when coding-agent commits fall back to the user's default Git configuration.
41473
41607
  */
41474
- function readRequiredEnvValue(name) {
41608
+ function printAgentGitIdentityTipIfNeeded() {
41609
+ if (getAgentGitIdentity()) {
41610
+ return;
41611
+ }
41612
+ console.info(colors__default["default"].cyan(_spaceTrim.spaceTrim(`
41613
+ Tip: \`ptbk coder run\` used your default Git config because the coding-agent identity environment variables are incomplete.
41614
+ For cleaner commit history, set \`CODING_AGENT_GIT_NAME\`, \`CODING_AGENT_GIT_EMAIL\`, and either \`CODING_AGENT_GIT_SIGNING_KEY\` or \`CODING_AGENT_GPG_KEY_ID\`.
41615
+ `)));
41616
+ }
41617
+ /**
41618
+ * Reads one optional environment variable and trims it when present.
41619
+ */
41620
+ function readOptionalEnvValue(name) {
41475
41621
  var _a;
41476
41622
  const value = (_a = process.env[name]) === null || _a === void 0 ? void 0 : _a.trim();
41477
- if (!value) {
41478
- throw new Error(`Missing required environment variable ${name}. ` +
41479
- 'Set CODING_AGENT_GIT_NAME, CODING_AGENT_GIT_EMAIL, ' +
41480
- 'and CODING_AGENT_GIT_SIGNING_KEY before running the coding agent.');
41623
+ return value || undefined;
41624
+ }
41625
+ /**
41626
+ * Reads the first configured signing-key environment variable.
41627
+ */
41628
+ function readOptionalSigningKeyValue() {
41629
+ for (const envName of AGENT_GIT_SIGNING_KEY_ENV_ALIASES) {
41630
+ const value = readOptionalEnvValue(envName);
41631
+ if (value) {
41632
+ return value;
41633
+ }
41481
41634
  }
41482
- return value;
41635
+ return undefined;
41483
41636
  }
41484
41637
 
41485
41638
  /**
41486
- * Commits staged changes with the provided message using the configured agent identity and signing key.
41639
+ * Commits staged changes with the provided message using the dedicated coding-agent identity when configured,
41640
+ * otherwise falls back to the default Git configuration.
41487
41641
  */
41488
41642
  async function commitChanges(message) {
41489
41643
  const commitMessagePath = path.join(process.cwd(), '.tmp', 'codex-prompts', `COMMIT_MESSAGE_${Date.now()}.txt`);
@@ -41491,12 +41645,13 @@
41491
41645
  await promises.writeFile(commitMessagePath, message, 'utf-8');
41492
41646
  try {
41493
41647
  const agentEnv = buildAgentGitEnv();
41648
+ const signingFlag = buildAgentGitSigningFlag();
41494
41649
  await $execCommand({
41495
41650
  command: 'git add .',
41496
41651
  env: agentEnv,
41497
41652
  });
41498
41653
  await $execCommand({
41499
- command: `git commit ${buildAgentGitSigningFlag()} --file "${commitMessagePath}"`,
41654
+ command: buildGitCommitCommand(commitMessagePath, signingFlag),
41500
41655
  env: agentEnv,
41501
41656
  });
41502
41657
  await pushCommittedChanges(agentEnv);
@@ -41661,6 +41816,17 @@
41661
41816
  throw new GitPushFailedError(buildPushFailureMessage(command, error));
41662
41817
  }
41663
41818
  }
41819
+ /**
41820
+ * Builds the `git commit` command with an optional signing flag.
41821
+ */
41822
+ function buildGitCommitCommand(commitMessagePath, signingFlag) {
41823
+ const commandParts = ['git commit'];
41824
+ if (signingFlag) {
41825
+ commandParts.push(signingFlag);
41826
+ }
41827
+ commandParts.push(`--file "${commitMessagePath}"`);
41828
+ return commandParts.join(' ');
41829
+ }
41664
41830
  /**
41665
41831
  * Builds a failure message that includes actionable hints for common push problems.
41666
41832
  */
@@ -43912,15 +44078,25 @@
43912
44078
  const loginMethodConfig = options.allowCredits ? '' : ' -c forced_login_method=chatgpt \\';
43913
44079
  const modelReasoningEffortConfig = ' -c model_reasoning_effort="xhigh" \\';
43914
44080
  return spaceTrim((block) => `
44081
+
44082
+ if [ -f .env ]; then
44083
+ set -a
44084
+ source .env
44085
+ set +a
44086
+ fi
44087
+
44088
+ unset OPENAI_API_KEY
44089
+ unset OPENAI_BASE_URL
44090
+
43915
44091
  ${options.codexCommand} \\
43916
- ${loginMethodConfig}
43917
- ${modelReasoningEffortConfig}
43918
- --ask-for-approval ${options.askForApproval} \\
43919
- exec --model ${options.model} \\
43920
- --local-provider none \\
43921
- --sandbox ${options.sandbox} \\
43922
- -C ${projectPath} \\
43923
- <<'${delimiter}'
44092
+ ${loginMethodConfig}
44093
+ ${modelReasoningEffortConfig}
44094
+ --ask-for-approval ${options.askForApproval} \\
44095
+ exec --model ${options.model} \\
44096
+ --local-provider none \\
44097
+ --sandbox ${options.sandbox} \\
44098
+ -C ${projectPath} \\
44099
+ <<'${delimiter}'
43924
44100
 
43925
44101
  ${block(options.prompt)}
43926
44102
 
@@ -44618,6 +44794,9 @@
44618
44794
  }
44619
44795
  finally {
44620
44796
  progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.stop();
44797
+ if (!options.dryRun) {
44798
+ printAgentGitIdentityTipIfNeeded();
44799
+ }
44621
44800
  }
44622
44801
  }
44623
44802
  /**