@pantheon.ai/agents 0.3.2 → 0.3.4
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/dist/index.js
CHANGED
|
@@ -399,7 +399,7 @@ var require_cli_options = /* @__PURE__ */ __commonJSMin(((exports, module) => {
|
|
|
399
399
|
|
|
400
400
|
//#endregion
|
|
401
401
|
//#region package.json
|
|
402
|
-
var version = "0.3.
|
|
402
|
+
var version = "0.3.4";
|
|
403
403
|
|
|
404
404
|
//#endregion
|
|
405
405
|
//#region src/db/db9.ts
|
|
@@ -639,6 +639,7 @@ var TaskListDb9Provider = class extends TaskListProvider {
|
|
|
639
639
|
"agent_project_config.retry_backoff_seconds",
|
|
640
640
|
"agent_project_config.role",
|
|
641
641
|
"agent_project_config.skills",
|
|
642
|
+
"agent_project_config.envs",
|
|
642
643
|
"agent_project_config.prototype_url",
|
|
643
644
|
"agent_project_config.execute_agent"
|
|
644
645
|
]).select((eb) => eb.ref("task.status").$castTo().as("config_task_status")).where("agent_project_config.project_id", "=", projectId).where("agent_project_config.agent", "=", this.agentName).executeTakeFirst();
|
|
@@ -657,26 +658,30 @@ var TaskListDb9Provider = class extends TaskListProvider {
|
|
|
657
658
|
"agent_project_config.retry_backoff_seconds",
|
|
658
659
|
"agent_project_config.role",
|
|
659
660
|
"agent_project_config.skills",
|
|
661
|
+
"agent_project_config.envs",
|
|
660
662
|
"agent_project_config.prototype_url",
|
|
661
663
|
"agent_project_config.execute_agent"
|
|
662
664
|
]).select((eb) => eb.ref("task.status").$castTo().as("config_task_status")).where("agent_project_config.agent", "=", this.agentName).execute();
|
|
663
665
|
}
|
|
664
|
-
async setAgentConfig({ skills, ...config }) {
|
|
666
|
+
async setAgentConfig({ skills, envs, ...config }) {
|
|
665
667
|
const maxRetryAttempts = config.max_retry_attempts ?? 3;
|
|
666
668
|
const retryBackoffSeconds = config.retry_backoff_seconds ?? 30;
|
|
667
669
|
await this.db.insertInto("agent_project_config").values({
|
|
668
670
|
agent: this.agentName,
|
|
669
671
|
skills: JSON.stringify(skills),
|
|
672
|
+
envs: JSON.stringify(envs ?? {}),
|
|
670
673
|
...config,
|
|
671
674
|
max_retry_attempts: maxRetryAttempts,
|
|
672
675
|
retry_backoff_seconds: retryBackoffSeconds
|
|
673
676
|
}).execute();
|
|
674
677
|
}
|
|
675
|
-
async updateAgentConfig({ skills, ...config }) {
|
|
678
|
+
async updateAgentConfig({ skills, envs, ...config }) {
|
|
676
679
|
const maxRetryAttempts = config.max_retry_attempts;
|
|
677
680
|
const retryBackoffSeconds = config.retry_backoff_seconds;
|
|
681
|
+
const resolvedEnvs = envs == null ? void 0 : JSON.stringify(envs);
|
|
678
682
|
const result = await this.db.updateTable("agent_project_config").set({
|
|
679
683
|
skills: JSON.stringify(skills),
|
|
684
|
+
...resolvedEnvs == null ? {} : { envs: resolvedEnvs },
|
|
680
685
|
...config,
|
|
681
686
|
...maxRetryAttempts == null ? {} : { max_retry_attempts: maxRetryAttempts },
|
|
682
687
|
...retryBackoffSeconds == null ? {} : { retry_backoff_seconds: retryBackoffSeconds }
|
|
@@ -783,22 +788,25 @@ var TaskListTidbProvider = class extends TaskListProvider {
|
|
|
783
788
|
async getAgentConfigs() {
|
|
784
789
|
return await this.db.selectFrom("agent_project_config").innerJoin("task", "task.id", "agent_project_config.config_task_id").selectAll("agent_project_config").select((eb) => eb.ref("task.status").$castTo().as("config_task_status")).where("agent_project_config.agent", "=", this.agentName).execute();
|
|
785
790
|
}
|
|
786
|
-
async setAgentConfig({ skills, ...config }) {
|
|
791
|
+
async setAgentConfig({ skills, envs, ...config }) {
|
|
787
792
|
const maxRetryAttempts = config.max_retry_attempts ?? 3;
|
|
788
793
|
const retryBackoffSeconds = config.retry_backoff_seconds ?? 30;
|
|
789
794
|
await this.db.insertInto("agent_project_config").values({
|
|
790
795
|
agent: this.agentName,
|
|
791
796
|
skills: JSON.stringify(skills),
|
|
797
|
+
envs: JSON.stringify(envs ?? {}),
|
|
792
798
|
...config,
|
|
793
799
|
max_retry_attempts: maxRetryAttempts,
|
|
794
800
|
retry_backoff_seconds: retryBackoffSeconds
|
|
795
801
|
}).execute();
|
|
796
802
|
}
|
|
797
|
-
async updateAgentConfig({ skills, ...config }) {
|
|
803
|
+
async updateAgentConfig({ skills, envs, ...config }) {
|
|
798
804
|
const maxRetryAttempts = config.max_retry_attempts;
|
|
799
805
|
const retryBackoffSeconds = config.retry_backoff_seconds;
|
|
806
|
+
const resolvedEnvs = envs == null ? void 0 : JSON.stringify(envs);
|
|
800
807
|
const result = await this.db.updateTable("agent_project_config").set({
|
|
801
808
|
skills: JSON.stringify(skills),
|
|
809
|
+
...resolvedEnvs == null ? {} : { envs: resolvedEnvs },
|
|
802
810
|
...config,
|
|
803
811
|
...maxRetryAttempts == null ? {} : { max_retry_attempts: maxRetryAttempts },
|
|
804
812
|
...retryBackoffSeconds == null ? {} : { retry_backoff_seconds: retryBackoffSeconds }
|
|
@@ -902,6 +910,20 @@ function normalizeSkills(value) {
|
|
|
902
910
|
}
|
|
903
911
|
return [];
|
|
904
912
|
}
|
|
913
|
+
function normalizeEnvs(value) {
|
|
914
|
+
const parseRecord = (input) => {
|
|
915
|
+
if (!input || typeof input !== "object" || Array.isArray(input)) return {};
|
|
916
|
+
const result = {};
|
|
917
|
+
for (const [key, item] of Object.entries(input)) if (typeof item === "string") result[key] = item;
|
|
918
|
+
return result;
|
|
919
|
+
};
|
|
920
|
+
if (typeof value === "string") try {
|
|
921
|
+
return parseRecord(JSON.parse(value));
|
|
922
|
+
} catch {
|
|
923
|
+
return {};
|
|
924
|
+
}
|
|
925
|
+
return parseRecord(value);
|
|
926
|
+
}
|
|
905
927
|
function buildConfigSetupStep(options) {
|
|
906
928
|
const prototypeRepoUrl = normalizeRepoUrl(options.prototypeRepoUrl);
|
|
907
929
|
const skillsArg = JSON.stringify(options.skills.join(","));
|
|
@@ -1787,6 +1809,7 @@ const listProjectBackgroundTasks = defineApi(get`/api/v1/projects/${"projectId"}
|
|
|
1787
1809
|
const createProjectExploration = defineApi(post`/api/v1/projects/${"projectId"}/explorations`, typeOf(), createExplorationResultSchema);
|
|
1788
1810
|
const listProjectExplorations = defineApi(get`/api/v1/projects/${"projectId"}/explorations`, null, explorationSchema.array());
|
|
1789
1811
|
const getProjectExplorationResult = defineApi(get`/api/v1/projects/${"projectId"}/explorations/${"explorationId"}/result`, null, explorationResultSchema);
|
|
1812
|
+
const killProjectBranch = defineApi(post`/api/v1/projects/${"projectId"}/branches/${"branchId"}/kill`, typeOf(), snapSchema.nullable());
|
|
1790
1813
|
const getProjectBranchFs = defineApi(get`/api/v1/projects/${"projectId"}/branches/${"branchId"}/fs/${"path*"}`, null, FSResponseValidator);
|
|
1791
1814
|
const getProjectBranchFsPreview = defineApi(get`/api/v1/projects/${"projectId"}/branches/${"branchId"}/preview/${"path*"}`, null, FSResponseValidator);
|
|
1792
1815
|
|
|
@@ -2027,7 +2050,6 @@ const executor = createApiExecutor({
|
|
|
2027
2050
|
headers: { Authorization: `Bearer ${process.env.PANTHEON_API_KEY}` },
|
|
2028
2051
|
validateResponse
|
|
2029
2052
|
});
|
|
2030
|
-
const killProjectBranchExecutionApi = defineApi(post`/api/v1/projects/${"projectId"}/branches/${"branchId"}/kill`, typeOf(), "raw");
|
|
2031
2053
|
async function getPantheonProjectInfo({ projectId }) {
|
|
2032
2054
|
return await executor.execute(getProject, { projectId }, null);
|
|
2033
2055
|
}
|
|
@@ -2076,13 +2098,14 @@ async function getPantheonBranchInfo({ projectId, branchId }) {
|
|
|
2076
2098
|
branchId
|
|
2077
2099
|
}, null);
|
|
2078
2100
|
}
|
|
2079
|
-
async function executeOnPantheon({ projectId, branchId, prompt, agent }) {
|
|
2101
|
+
async function executeOnPantheon({ projectId, branchId, prompt, agent, envs }) {
|
|
2080
2102
|
const promptSequence = Array.isArray(prompt) ? prompt : [prompt];
|
|
2081
2103
|
return (await executor.execute(createProjectExploration, { projectId }, {
|
|
2082
2104
|
shared_prompt_sequence: promptSequence,
|
|
2083
2105
|
num_branches: 1,
|
|
2084
2106
|
agent,
|
|
2085
|
-
parent_branch_id: branchId
|
|
2107
|
+
parent_branch_id: branchId,
|
|
2108
|
+
envs
|
|
2086
2109
|
})).branches[0];
|
|
2087
2110
|
}
|
|
2088
2111
|
function isNotFoundError(error) {
|
|
@@ -2092,7 +2115,7 @@ function isNotFoundError(error) {
|
|
|
2092
2115
|
}
|
|
2093
2116
|
async function killPantheonBranchExecution({ projectId, branchId }) {
|
|
2094
2117
|
try {
|
|
2095
|
-
await executor.execute(
|
|
2118
|
+
await executor.execute(killProjectBranch, {
|
|
2096
2119
|
projectId,
|
|
2097
2120
|
branchId
|
|
2098
2121
|
}, {});
|
|
@@ -2246,6 +2269,7 @@ async function pollRunningTaskState(provider, state, logger) {
|
|
|
2246
2269
|
execute_agent: config.execute_agent,
|
|
2247
2270
|
role: config.role,
|
|
2248
2271
|
skills: normalizeSkills(config.skills),
|
|
2272
|
+
envs: normalizeEnvs(config.envs),
|
|
2249
2273
|
prototype_url: config.prototype_url
|
|
2250
2274
|
});
|
|
2251
2275
|
} else if (newStatus.state === "failed") {
|
|
@@ -2350,7 +2374,8 @@ async function startPendingTask(provider, task, config, logger) {
|
|
|
2350
2374
|
projectId: taskToStart.project_id,
|
|
2351
2375
|
branchId: taskToStart.base_branch_id,
|
|
2352
2376
|
prompt: promptSequence,
|
|
2353
|
-
agent: config.execute_agent
|
|
2377
|
+
agent: config.execute_agent,
|
|
2378
|
+
envs: normalizeEnvs(config.envs)
|
|
2354
2379
|
});
|
|
2355
2380
|
});
|
|
2356
2381
|
logger.info(`Task ${taskToStart.id} started successfully on branch [id = ${taskBranch.branch_id}, snap_id = ${taskBranch.latest_snap_id}]`);
|
|
@@ -2407,7 +2432,7 @@ async function preparePendingTaskForStart(provider, task, config, logger) {
|
|
|
2407
2432
|
}
|
|
2408
2433
|
return task;
|
|
2409
2434
|
}
|
|
2410
|
-
if (task.type
|
|
2435
|
+
if (task.type === "bootstrap") return task;
|
|
2411
2436
|
const parentTask = await provider.getTask(task.parent_task_id);
|
|
2412
2437
|
if (!parentTask) {
|
|
2413
2438
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -2430,6 +2455,16 @@ async function preparePendingTaskForStart(provider, task, config, logger) {
|
|
|
2430
2455
|
logger.info(`Task ${task.id} is waiting because parent task ${parentTask.id} is ${parentTask.status}; only completed parent can start child.`);
|
|
2431
2456
|
return null;
|
|
2432
2457
|
}
|
|
2458
|
+
if (task.type === "reconfig") {
|
|
2459
|
+
const parentBranchId = getTaskWorkingBranchId(parentTask);
|
|
2460
|
+
if (task.base_branch_id === parentBranchId) return task;
|
|
2461
|
+
const updatedTask = {
|
|
2462
|
+
...task,
|
|
2463
|
+
base_branch_id: parentBranchId
|
|
2464
|
+
};
|
|
2465
|
+
await provider.updateTask(updatedTask);
|
|
2466
|
+
return updatedTask;
|
|
2467
|
+
}
|
|
2433
2468
|
if (parentTask.config_version !== config.config_version) {
|
|
2434
2469
|
await handleOutdatedParentAtStart(provider, task, parentTask, parentTask.config_version, config.config_version, logger);
|
|
2435
2470
|
return null;
|
|
@@ -2877,6 +2912,7 @@ async function configAgent(name, options) {
|
|
|
2877
2912
|
return;
|
|
2878
2913
|
}
|
|
2879
2914
|
const resolvedSkills = options.skills ?? normalizeSkills(previousConfig?.skills);
|
|
2915
|
+
const resolvedEnvs = options.envs ?? normalizeEnvs(previousConfig?.envs);
|
|
2880
2916
|
const resolvedExecuteAgent = options.executeAgent.trim() || previousConfig?.execute_agent || "codex";
|
|
2881
2917
|
const resolvedPrototypeUrl = options.prototypeUrl.trim() || previousConfig?.prototype_url || "https://github.com/pingcap-inc/pantheon-agents";
|
|
2882
2918
|
const baseBranchId = previousConfig ? previousConfig.base_branch_id : await resolveInitialBaseBranchId(options.projectId, options.rootBranchId);
|
|
@@ -2911,6 +2947,7 @@ async function configAgent(name, options) {
|
|
|
2911
2947
|
execute_agent: resolvedExecuteAgent,
|
|
2912
2948
|
role: resolvedRole ?? previousConfig.role,
|
|
2913
2949
|
skills: resolvedSkills,
|
|
2950
|
+
envs: resolvedEnvs,
|
|
2914
2951
|
prototype_url: resolvedPrototypeUrl
|
|
2915
2952
|
});
|
|
2916
2953
|
if (!options.prompt) await provider.updateTask({
|
|
@@ -2980,6 +3017,7 @@ async function configAgent(name, options) {
|
|
|
2980
3017
|
execute_agent: resolvedExecuteAgent,
|
|
2981
3018
|
role: resolvedRole,
|
|
2982
3019
|
skills: resolvedSkills,
|
|
3020
|
+
envs: resolvedEnvs,
|
|
2983
3021
|
prototype_url: resolvedPrototypeUrl
|
|
2984
3022
|
});
|
|
2985
3023
|
else await provider.updateAgentConfig({
|
|
@@ -2993,6 +3031,7 @@ async function configAgent(name, options) {
|
|
|
2993
3031
|
execute_agent: resolvedExecuteAgent,
|
|
2994
3032
|
role: resolvedRole ?? previousConfig.role,
|
|
2995
3033
|
skills: resolvedSkills,
|
|
3034
|
+
envs: resolvedEnvs,
|
|
2996
3035
|
prototype_url: resolvedPrototypeUrl
|
|
2997
3036
|
});
|
|
2998
3037
|
for (const pendingTask of pendingTasks) {
|
|
@@ -3549,8 +3588,25 @@ function parsePositiveInteger(value, fieldName) {
|
|
|
3549
3588
|
if (!Number.isInteger(parsed) || parsed <= 0) throw new InvalidArgumentError(`${fieldName} must be a positive integer.`);
|
|
3550
3589
|
return parsed;
|
|
3551
3590
|
}
|
|
3591
|
+
function parseEnvs(value) {
|
|
3592
|
+
const trimmed = value.trim();
|
|
3593
|
+
if (!trimmed) throw new InvalidArgumentError("envs must be a JSON object of string values.");
|
|
3594
|
+
let parsed;
|
|
3595
|
+
try {
|
|
3596
|
+
parsed = JSON.parse(trimmed);
|
|
3597
|
+
} catch {
|
|
3598
|
+
throw new InvalidArgumentError("envs must be valid JSON.");
|
|
3599
|
+
}
|
|
3600
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new InvalidArgumentError("envs must be a JSON object.");
|
|
3601
|
+
const out = {};
|
|
3602
|
+
for (const [key, item] of Object.entries(parsed)) {
|
|
3603
|
+
if (typeof item !== "string") throw new InvalidArgumentError(`envs.${key} must be a string value.`);
|
|
3604
|
+
out[key] = item;
|
|
3605
|
+
}
|
|
3606
|
+
return out;
|
|
3607
|
+
}
|
|
3552
3608
|
function createConfigAgentCommand(version, deps = {}) {
|
|
3553
|
-
return createCommand("config").version(version).description("Queue a configuration task for an agent/project").argument("<name>", "The name of the agent.").argument("[prompt]", "The configuration task prompt.").option("--project-id <project-id>", "The project id of the agent. Defaults to DEFAULT_PANTHEON_PROJECT_ID.").option("--task-id <task-id>", "Optional parent task id.").option("--role <role>", "Role metadata. Required for first-time project config; optional override later.").option("--skills <skills>", "The skills of the agent. Multiple values are separated by comma.", parseUniqueCommaList).option("--execute-agent <agent>", "The execute agent of the agent.", "codex").option("--concurrency <number>", "Max number of parallel running tasks for this project.", parseConcurrency).option("--max-retry-attempts <number>", "Max automatic retry attempts per task after failures.", (value) => parseNonNegativeInteger(value, "max-retry-attempts")).option("--retry-backoff-seconds <seconds>", "Base delay (seconds) for exponential retry backoff.", (value) => parsePositiveInteger(value, "retry-backoff-seconds")).option("--root-branch-id <branchId>", "The root branch id of the agent. Defaults to DEFAULT_PANTHEON_ROOT_BRANCH_ID, then project root branch id.").option("--prototype-url <url>", "Role and skill definitions repo.", "https://github.com/pingcap-inc/pantheon-agents").action(async function() {
|
|
3609
|
+
return createCommand("config").version(version).description("Queue a configuration task for an agent/project").argument("<name>", "The name of the agent.").argument("[prompt]", "The configuration task prompt.").option("--project-id <project-id>", "The project id of the agent. Defaults to DEFAULT_PANTHEON_PROJECT_ID.").option("--task-id <task-id>", "Optional parent task id.").option("--role <role>", "Role metadata. Required for first-time project config; optional override later.").option("--skills <skills>", "The skills of the agent. Multiple values are separated by comma.", parseUniqueCommaList).option("--execute-agent <agent>", "The execute agent of the agent.", "codex").option("--concurrency <number>", "Max number of parallel running tasks for this project.", parseConcurrency).option("--max-retry-attempts <number>", "Max automatic retry attempts per task after failures.", (value) => parseNonNegativeInteger(value, "max-retry-attempts")).option("--retry-backoff-seconds <seconds>", "Base delay (seconds) for exponential retry backoff.", (value) => parsePositiveInteger(value, "retry-backoff-seconds")).option("--root-branch-id <branchId>", "The root branch id of the agent. Defaults to DEFAULT_PANTHEON_ROOT_BRANCH_ID, then project root branch id.").option("--prototype-url <url>", "Role and skill definitions repo.", "https://github.com/pingcap-inc/pantheon-agents").option("--envs <json>", "Pantheon branch envs in JSON object format, e.g. '{\"ANTHROPIC_MODEL\":\"claude-opus-4-5\"}'.", parseEnvs).action(async function() {
|
|
3554
3610
|
const [name, prompt] = this.args;
|
|
3555
3611
|
const options = this.opts();
|
|
3556
3612
|
const resolvedProjectId = resolvePantheonProjectId(options.projectId);
|
|
@@ -3571,6 +3627,7 @@ function createConfigAgentCommand(version, deps = {}) {
|
|
|
3571
3627
|
maxRetryAttempts: options.maxRetryAttempts,
|
|
3572
3628
|
retryBackoffSeconds: options.retryBackoffSeconds,
|
|
3573
3629
|
skills: options.skills,
|
|
3630
|
+
envs: options.envs,
|
|
3574
3631
|
prototypeUrl: options.prototypeUrl,
|
|
3575
3632
|
rootBranchId: resolvedRootBranchId
|
|
3576
3633
|
});
|
|
@@ -3774,7 +3831,8 @@ function createShowConfigCommand(version) {
|
|
|
3774
3831
|
role: config.role,
|
|
3775
3832
|
execute_agent: config.execute_agent,
|
|
3776
3833
|
prototype_url: config.prototype_url,
|
|
3777
|
-
skills: Array.isArray(config.skills) ? config.skills.join(", ") : String(config.skills)
|
|
3834
|
+
skills: Array.isArray(config.skills) ? config.skills.join(", ") : String(config.skills),
|
|
3835
|
+
envs: config.envs && typeof config.envs === "object" ? JSON.stringify(config.envs) : String(config.envs ?? "{}")
|
|
3778
3836
|
}]);
|
|
3779
3837
|
return;
|
|
3780
3838
|
}
|
|
@@ -3800,7 +3858,8 @@ function createShowConfigCommand(version) {
|
|
|
3800
3858
|
role: config.role,
|
|
3801
3859
|
execute_agent: config.execute_agent,
|
|
3802
3860
|
prototype_url: config.prototype_url,
|
|
3803
|
-
skills: Array.isArray(config.skills) ? config.skills.join(", ") : String(config.skills)
|
|
3861
|
+
skills: Array.isArray(config.skills) ? config.skills.join(", ") : String(config.skills),
|
|
3862
|
+
envs: config.envs && typeof config.envs === "object" ? JSON.stringify(config.envs) : String(config.envs ?? "{}")
|
|
3804
3863
|
})));
|
|
3805
3864
|
});
|
|
3806
3865
|
}
|