agentplane 0.2.17 → 0.2.18
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/assets/AGENTS.md +14 -3
- package/dist/backends/task-backend/redmine/env.d.ts +16 -0
- package/dist/backends/task-backend/redmine/env.d.ts.map +1 -0
- package/dist/backends/task-backend/redmine/env.js +61 -0
- package/dist/backends/task-backend/redmine/mapping.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine/mapping.js +25 -3
- package/dist/backends/task-backend/redmine-backend.d.ts +1 -1
- package/dist/backends/task-backend/redmine-backend.d.ts.map +1 -1
- package/dist/backends/task-backend/redmine-backend.js +31 -21
- package/dist/backends/task-backend/shared/errors.d.ts +2 -1
- package/dist/backends/task-backend/shared/errors.d.ts.map +1 -1
- package/dist/backends/task-backend/shared/errors.js +6 -2
- package/dist/cli/run-cli/commands/init/ui.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/ui.js +5 -3
- package/dist/cli/run-cli/commands/init/write-env.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init/write-env.js +14 -6
- package/dist/cli/run-cli/commands/init.d.ts +1 -1
- package/dist/cli/run-cli/commands/init.d.ts.map +1 -1
- package/dist/cli/run-cli/commands/init.js +6 -68
- package/dist/cli/run-cli.d.ts.map +1 -1
- package/dist/cli/run-cli.js +5 -1
- package/dist/cli/run-cli.test-helpers.d.ts.map +1 -1
- package/dist/cli/run-cli.test-helpers.js +14 -2
- package/dist/cli/shared/ansi.d.ts +3 -0
- package/dist/cli/shared/ansi.d.ts.map +1 -0
- package/dist/cli/shared/ansi.js +19 -0
- package/dist/commands/block.run.d.ts.map +1 -1
- package/dist/commands/block.run.js +1 -0
- package/dist/commands/block.spec.d.ts +1 -0
- package/dist/commands/block.spec.d.ts.map +1 -1
- package/dist/commands/block.spec.js +7 -0
- package/dist/commands/branch/remove.command.d.ts +1 -0
- package/dist/commands/branch/remove.command.d.ts.map +1 -1
- package/dist/commands/branch/remove.command.js +8 -0
- package/dist/commands/branch/remove.d.ts +1 -0
- package/dist/commands/branch/remove.d.ts.map +1 -1
- package/dist/commands/branch/remove.js +9 -0
- package/dist/commands/doctor.run.d.ts.map +1 -1
- package/dist/commands/doctor.run.js +67 -0
- package/dist/commands/finish.run.d.ts.map +1 -1
- package/dist/commands/finish.run.js +1 -0
- package/dist/commands/finish.spec.d.ts +1 -0
- package/dist/commands/finish.spec.d.ts.map +1 -1
- package/dist/commands/finish.spec.js +7 -0
- package/dist/commands/guard/impl/commands.d.ts.map +1 -1
- package/dist/commands/guard/impl/commands.js +50 -0
- package/dist/commands/guard/impl/comment-commit.js +1 -1
- package/dist/commands/release/apply.command.d.ts.map +1 -1
- package/dist/commands/release/apply.command.js +39 -1
- package/dist/commands/shared/approval-requirements.d.ts +18 -0
- package/dist/commands/shared/approval-requirements.d.ts.map +1 -0
- package/dist/commands/shared/approval-requirements.js +77 -0
- package/dist/commands/shared/network-approval.d.ts.map +1 -1
- package/dist/commands/shared/network-approval.js +8 -23
- package/dist/commands/start.run.d.ts.map +1 -1
- package/dist/commands/start.run.js +1 -0
- package/dist/commands/start.spec.d.ts +1 -0
- package/dist/commands/start.spec.d.ts.map +1 -1
- package/dist/commands/start.spec.js +7 -0
- package/dist/commands/task/block.d.ts +1 -0
- package/dist/commands/task/block.d.ts.map +1 -1
- package/dist/commands/task/block.js +9 -0
- package/dist/commands/task/finish.d.ts +1 -0
- package/dist/commands/task/finish.d.ts.map +1 -1
- package/dist/commands/task/finish.js +9 -0
- package/dist/commands/task/migrate.command.d.ts +1 -0
- package/dist/commands/task/migrate.command.d.ts.map +1 -1
- package/dist/commands/task/migrate.command.js +8 -0
- package/dist/commands/task/migrate.d.ts +1 -0
- package/dist/commands/task/migrate.d.ts.map +1 -1
- package/dist/commands/task/migrate.js +9 -3
- package/dist/commands/task/normalize.command.d.ts +1 -0
- package/dist/commands/task/normalize.command.d.ts.map +1 -1
- package/dist/commands/task/normalize.command.js +8 -0
- package/dist/commands/task/normalize.d.ts +1 -0
- package/dist/commands/task/normalize.d.ts.map +1 -1
- package/dist/commands/task/normalize.js +9 -3
- package/dist/commands/task/scaffold.command.d.ts +1 -0
- package/dist/commands/task/scaffold.command.d.ts.map +1 -1
- package/dist/commands/task/scaffold.command.js +8 -0
- package/dist/commands/task/scaffold.d.ts +1 -0
- package/dist/commands/task/scaffold.d.ts.map +1 -1
- package/dist/commands/task/scaffold.js +9 -0
- package/dist/commands/task/set-status.command.d.ts +1 -0
- package/dist/commands/task/set-status.command.d.ts.map +1 -1
- package/dist/commands/task/set-status.command.js +8 -0
- package/dist/commands/task/set-status.d.ts +1 -0
- package/dist/commands/task/set-status.d.ts.map +1 -1
- package/dist/commands/task/set-status.js +7 -8
- package/dist/commands/task/start.d.ts +1 -0
- package/dist/commands/task/start.d.ts.map +1 -1
- package/dist/commands/task/start.js +9 -0
- package/package.json +2 -2
package/assets/AGENTS.md
CHANGED
|
@@ -118,10 +118,21 @@ Outside-repo includes (non-exhaustive):
|
|
|
118
118
|
- `handoff_conditions`: conditions that trigger handoff to another role
|
|
119
119
|
- `unsafe_actions_requiring_explicit_user_ok`: actions that require explicit user confirmation
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
Approval escalation semantics:
|
|
122
122
|
|
|
123
|
-
-
|
|
124
|
-
-
|
|
123
|
+
- `execution` MAY raise approval requirements for specific actions (`network_access`, `force_action`).
|
|
124
|
+
- `execution` does not add new CLI capabilities; it only changes whether explicit approval is required.
|
|
125
|
+
- Capability boundaries remain defined by CLI commands + this policy.
|
|
126
|
+
|
|
127
|
+
Profile matrix:
|
|
128
|
+
|
|
129
|
+
- `conservative`: require approval for `network_access` and `force_action` (even if baseline approvals disable them).
|
|
130
|
+
- `balanced`: use baseline approvals from `agents.approvals`.
|
|
131
|
+
- `aggressive`: use baseline approvals from `agents.approvals`.
|
|
132
|
+
|
|
133
|
+
Precedence:
|
|
134
|
+
|
|
135
|
+
- Role authority boundaries, source-of-truth order, and hard invariants in this `AGENTS.md` still take precedence.
|
|
125
136
|
- If `execution` config conflicts with policy, `AGENTS.md` policy wins.
|
|
126
137
|
|
|
127
138
|
## Framework Upgrade / Prompt Merge
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type RedmineEnvConfig = {
|
|
2
|
+
url?: string;
|
|
3
|
+
apiKey?: string;
|
|
4
|
+
projectId?: string;
|
|
5
|
+
assigneeId?: number;
|
|
6
|
+
ownerAgent?: string;
|
|
7
|
+
customFields: Partial<Record<RedmineCustomFieldKey, number>>;
|
|
8
|
+
batch: {
|
|
9
|
+
size?: number;
|
|
10
|
+
pauseMs?: number;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
type RedmineCustomFieldKey = "task_id" | "doc" | "doc_version" | "doc_updated_at" | "doc_updated_by" | "tags" | "priority" | "owner";
|
|
14
|
+
export declare function readRedmineEnv(): RedmineEnvConfig;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=env.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/redmine/env.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7D,KAAK,EAAE;QACL,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;CACH,CAAC;AAEF,KAAK,qBAAqB,GACtB,SAAS,GACT,KAAK,GACL,aAAa,GACb,gBAAgB,GAChB,gBAAgB,GAChB,MAAM,GACN,UAAU,GACV,OAAO,CAAC;AA6BZ,wBAAgB,cAAc,IAAI,gBAAgB,CAiCjD"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { BackendError, redmineConfigInvalidEnvMessage } from "../shared.js";
|
|
2
|
+
function nonEmptyEnv(key) {
|
|
3
|
+
const value = process.env[key];
|
|
4
|
+
if (typeof value !== "string")
|
|
5
|
+
return undefined;
|
|
6
|
+
const trimmed = value.trim();
|
|
7
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
8
|
+
}
|
|
9
|
+
function parsePositiveIntEnv(key, opts) {
|
|
10
|
+
const raw = nonEmptyEnv(key);
|
|
11
|
+
if (!raw)
|
|
12
|
+
return undefined;
|
|
13
|
+
if (!/^\d+$/u.test(raw)) {
|
|
14
|
+
throw new BackendError(redmineConfigInvalidEnvMessage(key, "a positive integer"), "E_BACKEND");
|
|
15
|
+
}
|
|
16
|
+
const parsed = Number(raw);
|
|
17
|
+
const min = opts?.min ?? (opts?.allowZero ? 0 : 1);
|
|
18
|
+
if (!Number.isFinite(parsed) || parsed < min) {
|
|
19
|
+
throw new BackendError(redmineConfigInvalidEnvMessage(key, `an integer >= ${min}`), "E_BACKEND");
|
|
20
|
+
}
|
|
21
|
+
return parsed;
|
|
22
|
+
}
|
|
23
|
+
export function readRedmineEnv() {
|
|
24
|
+
const customFields = {};
|
|
25
|
+
const taskId = parsePositiveIntEnv("AGENTPLANE_REDMINE_CUSTOM_FIELDS_TASK_ID");
|
|
26
|
+
if (taskId !== undefined)
|
|
27
|
+
customFields.task_id = taskId;
|
|
28
|
+
const doc = parsePositiveIntEnv("AGENTPLANE_REDMINE_CUSTOM_FIELDS_DOC");
|
|
29
|
+
if (doc !== undefined)
|
|
30
|
+
customFields.doc = doc;
|
|
31
|
+
const docVersion = parsePositiveIntEnv("AGENTPLANE_REDMINE_CUSTOM_FIELDS_DOC_VERSION");
|
|
32
|
+
if (docVersion !== undefined)
|
|
33
|
+
customFields.doc_version = docVersion;
|
|
34
|
+
const docUpdatedAt = parsePositiveIntEnv("AGENTPLANE_REDMINE_CUSTOM_FIELDS_DOC_UPDATED_AT");
|
|
35
|
+
if (docUpdatedAt !== undefined)
|
|
36
|
+
customFields.doc_updated_at = docUpdatedAt;
|
|
37
|
+
const docUpdatedBy = parsePositiveIntEnv("AGENTPLANE_REDMINE_CUSTOM_FIELDS_DOC_UPDATED_BY");
|
|
38
|
+
if (docUpdatedBy !== undefined)
|
|
39
|
+
customFields.doc_updated_by = docUpdatedBy;
|
|
40
|
+
const tags = parsePositiveIntEnv("AGENTPLANE_REDMINE_CUSTOM_FIELDS_TAGS");
|
|
41
|
+
if (tags !== undefined)
|
|
42
|
+
customFields.tags = tags;
|
|
43
|
+
const priority = parsePositiveIntEnv("AGENTPLANE_REDMINE_CUSTOM_FIELDS_PRIORITY");
|
|
44
|
+
if (priority !== undefined)
|
|
45
|
+
customFields.priority = priority;
|
|
46
|
+
const owner = parsePositiveIntEnv("AGENTPLANE_REDMINE_CUSTOM_FIELDS_OWNER");
|
|
47
|
+
if (owner !== undefined)
|
|
48
|
+
customFields.owner = owner;
|
|
49
|
+
return {
|
|
50
|
+
url: nonEmptyEnv("AGENTPLANE_REDMINE_URL"),
|
|
51
|
+
apiKey: nonEmptyEnv("AGENTPLANE_REDMINE_API_KEY"),
|
|
52
|
+
projectId: nonEmptyEnv("AGENTPLANE_REDMINE_PROJECT_ID"),
|
|
53
|
+
assigneeId: parsePositiveIntEnv("AGENTPLANE_REDMINE_ASSIGNEE_ID"),
|
|
54
|
+
ownerAgent: nonEmptyEnv("AGENTPLANE_REDMINE_OWNER") ?? nonEmptyEnv("AGENTPLANE_REDMINE_OWNER_AGENT"),
|
|
55
|
+
customFields,
|
|
56
|
+
batch: {
|
|
57
|
+
size: parsePositiveIntEnv("AGENTPLANE_REDMINE_BATCH_SIZE"),
|
|
58
|
+
pauseMs: parsePositiveIntEnv("AGENTPLANE_REDMINE_BATCH_PAUSE", { allowZero: true, min: 0 }),
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/redmine/mapping.ts"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,QAAQ,EACd,MAAM,cAAc,CAAC;AAMtB,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASjE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIhE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,GAAG,QAAQ,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/redmine/mapping.ts"],"names":[],"mappings":"AAEA,OAAO,EAKL,KAAK,QAAQ,EACd,MAAM,cAAc,CAAC;AAMtB,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CASjE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAIhE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,GAAG,QAAQ,GAAG,IAAI,CAwElB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,IAAI,EAAE,QAAQ,CAAC;IACf,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CAC7F,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAyC1B"}
|
|
@@ -36,6 +36,9 @@ export function issueToTask(opts) {
|
|
|
36
36
|
const commitVal = customFieldValue(opts.issue, opts.customFields.commit);
|
|
37
37
|
const docVal = customFieldValue(opts.issue, opts.customFields.doc);
|
|
38
38
|
const commentsVal = customFieldValue(opts.issue, opts.customFields.comments);
|
|
39
|
+
const tagsVal = customFieldValue(opts.issue, opts.customFields.tags);
|
|
40
|
+
const priorityFieldVal = customFieldValue(opts.issue, opts.customFields.priority);
|
|
41
|
+
const ownerFieldVal = customFieldValue(opts.issue, opts.customFields.owner);
|
|
39
42
|
const docVersionVal = customFieldValue(opts.issue, opts.customFields.doc_version);
|
|
40
43
|
const docUpdatedAtVal = customFieldValue(opts.issue, opts.customFields.doc_updated_at);
|
|
41
44
|
const docUpdatedByVal = customFieldValue(opts.issue, opts.customFields.doc_updated_by);
|
|
@@ -45,7 +48,7 @@ export function issueToTask(opts) {
|
|
|
45
48
|
? opts.issue.created_on
|
|
46
49
|
: null;
|
|
47
50
|
const priorityVal = isRecord(opts.issue.priority) ? opts.issue.priority : null;
|
|
48
|
-
const priorityName = normalizePriority(priorityVal?.name);
|
|
51
|
+
const priorityName = normalizePriority(priorityVal?.name ?? priorityFieldVal);
|
|
49
52
|
const tags = [];
|
|
50
53
|
if (Array.isArray(opts.issue.tags)) {
|
|
51
54
|
for (const tag of opts.issue.tags) {
|
|
@@ -53,14 +56,30 @@ export function issueToTask(opts) {
|
|
|
53
56
|
tags.push(toStringSafe(tag.name));
|
|
54
57
|
}
|
|
55
58
|
}
|
|
59
|
+
const tagsFromField = maybeParseJson(tagsVal);
|
|
60
|
+
if (Array.isArray(tagsFromField)) {
|
|
61
|
+
for (const tag of tagsFromField) {
|
|
62
|
+
const text = toStringSafe(tag).trim();
|
|
63
|
+
if (text)
|
|
64
|
+
tags.push(text);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if (typeof tagsFromField === "string") {
|
|
68
|
+
for (const tag of tagsFromField.split(",")) {
|
|
69
|
+
const text = tag.trim();
|
|
70
|
+
if (text)
|
|
71
|
+
tags.push(text);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const mergedTags = [...new Set(tags)];
|
|
56
75
|
const task = {
|
|
57
76
|
id: toStringSafe(taskId),
|
|
58
77
|
title: toStringSafe(opts.issue.subject),
|
|
59
78
|
description: toStringSafe(opts.issue.description),
|
|
60
79
|
status: status ?? "TODO",
|
|
61
80
|
priority: priorityName,
|
|
62
|
-
owner: opts.ownerAgent,
|
|
63
|
-
tags,
|
|
81
|
+
owner: toStringSafe(ownerFieldVal ?? opts.ownerAgent),
|
|
82
|
+
tags: mergedTags,
|
|
64
83
|
depends_on: [],
|
|
65
84
|
verify: maybeParseJson(verifyVal),
|
|
66
85
|
commit: maybeParseJson(commitVal),
|
|
@@ -108,6 +127,9 @@ export function taskToIssuePayload(opts) {
|
|
|
108
127
|
opts.appendCustomField(customFields, "doc_version", opts.task.doc_version);
|
|
109
128
|
opts.appendCustomField(customFields, "doc_updated_at", opts.task.doc_updated_at);
|
|
110
129
|
opts.appendCustomField(customFields, "doc_updated_by", opts.task.doc_updated_by);
|
|
130
|
+
opts.appendCustomField(customFields, "tags", opts.task.tags);
|
|
131
|
+
opts.appendCustomField(customFields, "priority", opts.task.priority);
|
|
132
|
+
opts.appendCustomField(customFields, "owner", opts.task.owner);
|
|
111
133
|
if (customFields.length > 0)
|
|
112
134
|
payload.custom_fields = customFields;
|
|
113
135
|
return payload;
|
|
@@ -21,7 +21,7 @@ export declare class RedmineBackend implements TaskBackend {
|
|
|
21
21
|
statusMap: Record<string, unknown>;
|
|
22
22
|
customFields: Record<string, unknown>;
|
|
23
23
|
batchSize: number;
|
|
24
|
-
|
|
24
|
+
batchPauseMs: number;
|
|
25
25
|
cache: LocalBackend | null;
|
|
26
26
|
issueCache: Map<string, Record<string, unknown>>;
|
|
27
27
|
reverseStatus: Map<number, string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"redmine-backend.d.ts","sourceRoot":"","sources":["../../../src/backends/task-backend/redmine-backend.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"redmine-backend.d.ts","sourceRoot":"","sources":["../../../src/backends/task-backend/redmine-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,8 @@ import { appendCustomField as appendRedmineCustomField, customFieldValue as redm
|
|
|
6
6
|
import { doneRatioForStatus, issueToTask as issueToTaskImpl, startDateFromTaskId, taskToIssuePayload as taskToIssuePayloadImpl, } from "./redmine/mapping.js";
|
|
7
7
|
import { coerceDocVersion as coerceRedmineDocVersion, maybeParseJson as maybeParseRedmineJson, } from "./redmine/parse.js";
|
|
8
8
|
import { findIssueByTaskId as findIssueByTaskIdImpl, listTasksRemote as listTasksRemoteImpl, } from "./redmine/remote.js";
|
|
9
|
-
import {
|
|
9
|
+
import { readRedmineEnv } from "./redmine/env.js";
|
|
10
|
+
import { BackendError, DEFAULT_DOC_UPDATED_BY, DOC_VERSION, RedmineUnavailable, ensureDocMetadata, firstNonEmptyString, generateTaskId, mapLimit, missingTaskIdMessage, nowIso, redmineConfigMissingEnvMessage, redmineIssueIdMissingMessage, sleep, toStringSafe, unknownTaskIdMessage, validateTaskId, writeTasksExportFromTasks, } from "./shared.js";
|
|
10
11
|
export class RedmineBackend {
|
|
11
12
|
id = "redmine";
|
|
12
13
|
baseUrl;
|
|
@@ -17,25 +18,34 @@ export class RedmineBackend {
|
|
|
17
18
|
statusMap;
|
|
18
19
|
customFields;
|
|
19
20
|
batchSize;
|
|
20
|
-
|
|
21
|
+
batchPauseMs;
|
|
21
22
|
cache;
|
|
22
23
|
issueCache = new Map();
|
|
23
24
|
reverseStatus = new Map();
|
|
24
25
|
constructor(settings, opts) {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
this.baseUrl = firstNonEmptyString(envUrl, settings.url).replaceAll(/\/+$/gu, "");
|
|
31
|
-
this.apiKey = firstNonEmptyString(envApiKey, settings.api_key);
|
|
32
|
-
this.projectId = firstNonEmptyString(envProjectId, settings.project_id);
|
|
33
|
-
this.assigneeId = envAssignee && /^\d+$/u.test(envAssignee) ? Number(envAssignee) : null;
|
|
26
|
+
const env = readRedmineEnv();
|
|
27
|
+
this.baseUrl = firstNonEmptyString(env.url, settings.url).replaceAll(/\/+$/gu, "");
|
|
28
|
+
this.apiKey = firstNonEmptyString(env.apiKey, settings.api_key);
|
|
29
|
+
this.projectId = firstNonEmptyString(env.projectId, settings.project_id);
|
|
30
|
+
this.assigneeId = env.assigneeId ?? null;
|
|
34
31
|
this.statusMap = isRecord(settings.status_map) ? settings.status_map : {};
|
|
35
|
-
this.customFields =
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
32
|
+
this.customFields = {
|
|
33
|
+
...(isRecord(settings.custom_fields) ? settings.custom_fields : {}),
|
|
34
|
+
...env.customFields,
|
|
35
|
+
};
|
|
36
|
+
this.batchSize =
|
|
37
|
+
env.batch.size ??
|
|
38
|
+
(typeof settings.batch_size === "number" && Number.isFinite(settings.batch_size)
|
|
39
|
+
? Math.max(1, Math.trunc(settings.batch_size))
|
|
40
|
+
: 20);
|
|
41
|
+
this.batchPauseMs =
|
|
42
|
+
env.batch.pauseMs ??
|
|
43
|
+
(typeof settings.batch_pause === "number" && Number.isFinite(settings.batch_pause)
|
|
44
|
+
? settings.batch_pause >= 1
|
|
45
|
+
? Math.trunc(settings.batch_pause)
|
|
46
|
+
: Math.round(settings.batch_pause * 1000)
|
|
47
|
+
: 500);
|
|
48
|
+
this.ownerAgent = firstNonEmptyString(env.ownerAgent, settings.owner_agent, "REDMINE");
|
|
39
49
|
this.cache = opts.cache ?? null;
|
|
40
50
|
const missingEnvKeys = [];
|
|
41
51
|
if (!this.baseUrl)
|
|
@@ -45,10 +55,10 @@ export class RedmineBackend {
|
|
|
45
55
|
if (!this.projectId)
|
|
46
56
|
missingEnvKeys.push("AGENTPLANE_REDMINE_PROJECT_ID");
|
|
47
57
|
if (missingEnvKeys.length > 0) {
|
|
48
|
-
throw new BackendError(
|
|
58
|
+
throw new BackendError(redmineConfigMissingEnvMessage(missingEnvKeys), "E_BACKEND");
|
|
49
59
|
}
|
|
50
60
|
if (!this.customFields?.task_id) {
|
|
51
|
-
throw new BackendError(
|
|
61
|
+
throw new BackendError(redmineConfigMissingEnvMessage("AGENTPLANE_REDMINE_CUSTOM_FIELDS_TASK_ID"), "E_BACKEND");
|
|
52
62
|
}
|
|
53
63
|
for (const [key, value] of Object.entries(this.statusMap)) {
|
|
54
64
|
if (typeof value === "number")
|
|
@@ -136,7 +146,7 @@ export class RedmineBackend {
|
|
|
136
146
|
}
|
|
137
147
|
async setTaskDoc(taskId, doc, updatedBy) {
|
|
138
148
|
if (!this.customFields.doc) {
|
|
139
|
-
throw new BackendError(
|
|
149
|
+
throw new BackendError(redmineConfigMissingEnvMessage("AGENTPLANE_REDMINE_CUSTOM_FIELDS_DOC"), "E_BACKEND");
|
|
140
150
|
}
|
|
141
151
|
try {
|
|
142
152
|
const issue = await this.findIssueByTaskId(taskId);
|
|
@@ -281,8 +291,8 @@ export class RedmineBackend {
|
|
|
281
291
|
async writeTasks(tasks) {
|
|
282
292
|
for (const [index, task] of tasks.entries()) {
|
|
283
293
|
await this.writeTask(task);
|
|
284
|
-
if (this.
|
|
285
|
-
await sleep(this.
|
|
294
|
+
if (this.batchPauseMs > 0 && this.batchSize > 0 && (index + 1) % this.batchSize === 0) {
|
|
295
|
+
await sleep(this.batchPauseMs);
|
|
286
296
|
}
|
|
287
297
|
}
|
|
288
298
|
}
|
|
@@ -408,7 +418,7 @@ export class RedmineBackend {
|
|
|
408
418
|
const fieldId = this.customFields?.task_id;
|
|
409
419
|
if (fieldId)
|
|
410
420
|
return fieldId;
|
|
411
|
-
throw new BackendError(
|
|
421
|
+
throw new BackendError(redmineConfigMissingEnvMessage("AGENTPLANE_REDMINE_CUSTOM_FIELDS_TASK_ID"), "E_BACKEND");
|
|
412
422
|
}
|
|
413
423
|
setIssueCustomFieldValue(issue, fieldId, value) {
|
|
414
424
|
setRedmineIssueCustomFieldValue(issue, fieldId, value);
|
|
@@ -5,6 +5,7 @@ export declare class BackendError extends Error {
|
|
|
5
5
|
export declare class RedmineUnavailable extends BackendError {
|
|
6
6
|
constructor(message: string);
|
|
7
7
|
}
|
|
8
|
-
export declare function
|
|
8
|
+
export declare function redmineConfigMissingEnvMessage(keys: string[] | string): string;
|
|
9
|
+
export declare function redmineConfigInvalidEnvMessage(key: string, expected: string): string;
|
|
9
10
|
export declare function redmineIssueIdMissingMessage(): string;
|
|
10
11
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/shared/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,YAAa,SAAQ,KAAK;IACrC,IAAI,EAAE,WAAW,GAAG,WAAW,CAAC;gBACpB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,WAAW;CAI7D;AAED,qBAAa,kBAAmB,SAAQ,YAAY;gBACtC,OAAO,EAAE,MAAM;CAG5B;AAED,wBAAgB,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../../src/backends/task-backend/shared/errors.ts"],"names":[],"mappings":"AAAA,qBAAa,YAAa,SAAQ,KAAK;IACrC,IAAI,EAAE,WAAW,GAAG,WAAW,CAAC;gBACpB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,WAAW;CAI7D;AAED,qBAAa,kBAAmB,SAAQ,YAAY;gBACtC,OAAO,EAAE,MAAM;CAG5B;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,MAAM,CAG9E;AAED,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEpF;AAED,wBAAgB,4BAA4B,IAAI,MAAM,CAErD"}
|
|
@@ -10,8 +10,12 @@ export class RedmineUnavailable extends BackendError {
|
|
|
10
10
|
super(message, "E_NETWORK");
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
-
export function
|
|
14
|
-
|
|
13
|
+
export function redmineConfigMissingEnvMessage(keys) {
|
|
14
|
+
const list = Array.isArray(keys) ? keys : [keys];
|
|
15
|
+
return `Missing required Redmine configuration env key(s): ${list.join(", ")}. Set them in environment variables (for example via .env).`;
|
|
16
|
+
}
|
|
17
|
+
export function redmineConfigInvalidEnvMessage(key, expected) {
|
|
18
|
+
return `Invalid Redmine configuration env value for ${key}. Expected ${expected}.`;
|
|
15
19
|
}
|
|
16
20
|
export function redmineIssueIdMissingMessage() {
|
|
17
21
|
return "Missing Redmine issue id for task";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../../../../src/cli/run-cli/commands/init/ui.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../../../../src/cli/run-cli/commands/init/ui.ts"],"names":[],"mappings":"AAyBA,wBAAgB,iBAAiB,IAAI,MAAM,CAY1C;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAG5E"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { visibleLen } from "../../../shared/ansi.js";
|
|
1
2
|
function useColor() {
|
|
2
3
|
return process.stdout.isTTY === true && (process.env.TERM ?? "dumb") !== "dumb";
|
|
3
4
|
}
|
|
@@ -7,12 +8,13 @@ function color(text, code) {
|
|
|
7
8
|
return `\u001B[${code}m${text}\u001B[0m`;
|
|
8
9
|
}
|
|
9
10
|
function padLine(line, width) {
|
|
10
|
-
|
|
11
|
+
const lineLen = visibleLen(line);
|
|
12
|
+
if (lineLen >= width)
|
|
11
13
|
return line;
|
|
12
|
-
return `${line}${" ".repeat(width -
|
|
14
|
+
return `${line}${" ".repeat(width - lineLen)}`;
|
|
13
15
|
}
|
|
14
16
|
function box(lines) {
|
|
15
|
-
const width = Math.max(...lines.map((line) => line
|
|
17
|
+
const width = Math.max(...lines.map((line) => visibleLen(line)), 0);
|
|
16
18
|
const top = `┌${"─".repeat(width + 2)}┐`;
|
|
17
19
|
const body = lines.map((line) => `│ ${padLine(line, width)} │`);
|
|
18
20
|
const bottom = `└${"─".repeat(width + 2)}┘`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write-env.d.ts","sourceRoot":"","sources":["../../../../../src/cli/run-cli/commands/init/write-env.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"write-env.d.ts","sourceRoot":"","sources":["../../../../../src/cli/run-cli/commands/init/write-env.ts"],"names":[],"mappings":"AAmGA,wBAAsB,4BAA4B,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAU3F"}
|
|
@@ -56,13 +56,11 @@ function collectDefinedEnvKeys(dotEnvText) {
|
|
|
56
56
|
}
|
|
57
57
|
return keys;
|
|
58
58
|
}
|
|
59
|
-
|
|
60
|
-
const dotEnvPath = path.join(opts.gitRoot, ".env");
|
|
61
|
-
const existing = (await readTextIfExists(dotEnvPath)) ?? "";
|
|
59
|
+
function buildTemplateBlock(existing) {
|
|
62
60
|
const definedKeys = collectDefinedEnvKeys(existing);
|
|
63
61
|
const missing = REDMINE_ENV_TEMPLATE.filter((entry) => !definedKeys.has(entry.key));
|
|
64
62
|
if (missing.length === 0)
|
|
65
|
-
return;
|
|
63
|
+
return existing;
|
|
66
64
|
const required = missing.filter((item) => item.required);
|
|
67
65
|
const optional = missing.filter((item) => !item.required);
|
|
68
66
|
const requiredLines = required.flatMap((entry) => [
|
|
@@ -84,6 +82,16 @@ export async function ensureInitRedmineEnvTemplate(opts) {
|
|
|
84
82
|
];
|
|
85
83
|
const block = `${lines.join("\n")}\n`;
|
|
86
84
|
const prefix = existing.length > 0 && !existing.endsWith("\n") ? "\n\n" : existing.length > 0 ? "\n" : "";
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
return `${existing}${prefix}${block}`;
|
|
86
|
+
}
|
|
87
|
+
export async function ensureInitRedmineEnvTemplate(opts) {
|
|
88
|
+
const dotEnvExamplePath = path.join(opts.gitRoot, ".env.example");
|
|
89
|
+
const existingExample = (await readTextIfExists(dotEnvExamplePath)) ?? "";
|
|
90
|
+
const nextExample = buildTemplateBlock(existingExample);
|
|
91
|
+
await writeTextIfChanged(dotEnvExamplePath, nextExample);
|
|
92
|
+
const dotEnvPath = path.join(opts.gitRoot, ".env");
|
|
93
|
+
const existingEnv = await readTextIfExists(dotEnvPath);
|
|
94
|
+
if (existingEnv !== null)
|
|
95
|
+
return;
|
|
96
|
+
await writeTextIfChanged(dotEnvPath, nextExample);
|
|
89
97
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CommandHandler, CommandSpec } from "../../spec/spec.js";
|
|
2
|
-
type ExecutionProfile
|
|
2
|
+
import { type ExecutionProfile } from "@agentplaneorg/core";
|
|
3
3
|
type InitFlags = {
|
|
4
4
|
ide?: "codex" | "cursor" | "windsurf";
|
|
5
5
|
workflow?: "direct" | "branch_pr";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../src/cli/run-cli/commands/init.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../src/cli/run-cli/commands/init.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAItE,OAAO,EAGL,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAC;AAa7B,KAAK,SAAS,GAAG;IACf,GAAG,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,UAAU,CAAC;IACtC,QAAQ,CAAC,EAAE,QAAQ,GAAG,WAAW,CAAC;IAClC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAC9B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,OAAO,CAAC;CACd,CAAC;AAsBF,KAAK,UAAU,GAAG,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG;IAAE,GAAG,EAAE,OAAO,CAAA;CAAE,CAAC;AAE5D,eAAO,MAAM,QAAQ,EAAE,WAAW,CAAC,UAAU,CA2K5C,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,cAAc,CAAC,UAAU,CACmB,CAAC"}
|
|
@@ -7,82 +7,17 @@ import { usageError } from "../../spec/errors.js";
|
|
|
7
7
|
import { CliError } from "../../../shared/errors.js";
|
|
8
8
|
import { getVersion } from "../../../meta/version.js";
|
|
9
9
|
import { cmdHooksInstall, ensureInitCommit } from "../../../commands/workflow.js";
|
|
10
|
-
import { setPinnedBaseBranch } from "@agentplaneorg/core";
|
|
10
|
+
import { buildExecutionProfile, setPinnedBaseBranch, } from "@agentplaneorg/core";
|
|
11
11
|
import { resolveInitBaseBranchForInit } from "./init/base-branch.js";
|
|
12
12
|
import { collectInitConflicts, handleInitConflicts } from "./init/conflicts.js";
|
|
13
13
|
import { ensureGitRoot } from "./init/git.js";
|
|
14
14
|
import { maybeSyncIde } from "./init/ide-sync.js";
|
|
15
15
|
import { maybeInstallBundledRecipes } from "./init/recipes.js";
|
|
16
|
-
import { ensureAgentplaneDirs, writeBackendStubs, writeInitConfig
|
|
16
|
+
import { ensureAgentplaneDirs, writeBackendStubs, writeInitConfig } from "./init/write-config.js";
|
|
17
17
|
import { ensureAgentsFiles } from "./init/write-agents.js";
|
|
18
18
|
import { ensureInitGitignore } from "./init/write-gitignore.js";
|
|
19
19
|
import { ensureInitRedmineEnvTemplate } from "./init/write-env.js";
|
|
20
20
|
import { renderInitSection, renderInitWelcome } from "./init/ui.js";
|
|
21
|
-
function buildInitExecutionProfile(profile, opts) {
|
|
22
|
-
const shared = {
|
|
23
|
-
stop_conditions: [
|
|
24
|
-
"Missing required input blocks correctness.",
|
|
25
|
-
"Requested action expands scope or risk beyond approved plan.",
|
|
26
|
-
"Verification fails and remediation changes scope.",
|
|
27
|
-
],
|
|
28
|
-
handoff_conditions: [
|
|
29
|
-
"Role boundary reached (for example CODER -> TESTER/REVIEWER).",
|
|
30
|
-
"Task depends_on prerequisites are incomplete.",
|
|
31
|
-
"Specialized agent is required.",
|
|
32
|
-
],
|
|
33
|
-
};
|
|
34
|
-
const byProfile = {
|
|
35
|
-
conservative: {
|
|
36
|
-
profile: "conservative",
|
|
37
|
-
reasoning_effort: "high",
|
|
38
|
-
tool_budget: { discovery: 4, implementation: 8, verification: 8 },
|
|
39
|
-
...shared,
|
|
40
|
-
unsafe_actions_requiring_explicit_user_ok: [
|
|
41
|
-
"Destructive git history operations.",
|
|
42
|
-
"Outside-repo read/write.",
|
|
43
|
-
"Credential, keychain, or SSH material changes.",
|
|
44
|
-
"Network actions when approvals are enabled.",
|
|
45
|
-
],
|
|
46
|
-
},
|
|
47
|
-
balanced: {
|
|
48
|
-
profile: "balanced",
|
|
49
|
-
reasoning_effort: "medium",
|
|
50
|
-
tool_budget: { discovery: 6, implementation: 10, verification: 6 },
|
|
51
|
-
...shared,
|
|
52
|
-
unsafe_actions_requiring_explicit_user_ok: [
|
|
53
|
-
"Destructive git history operations.",
|
|
54
|
-
"Outside-repo read/write.",
|
|
55
|
-
"Credential, keychain, or SSH material changes.",
|
|
56
|
-
],
|
|
57
|
-
},
|
|
58
|
-
aggressive: {
|
|
59
|
-
profile: "aggressive",
|
|
60
|
-
reasoning_effort: "low",
|
|
61
|
-
tool_budget: { discovery: 10, implementation: 16, verification: 8 },
|
|
62
|
-
stop_conditions: [
|
|
63
|
-
"Requested action expands scope or risk beyond approved plan.",
|
|
64
|
-
"Verification fails and remediation changes scope.",
|
|
65
|
-
],
|
|
66
|
-
handoff_conditions: [
|
|
67
|
-
"Role boundary reached (for example CODER -> TESTER/REVIEWER).",
|
|
68
|
-
"Specialized agent is required.",
|
|
69
|
-
],
|
|
70
|
-
unsafe_actions_requiring_explicit_user_ok: [
|
|
71
|
-
"Destructive git history operations.",
|
|
72
|
-
"Outside-repo read/write.",
|
|
73
|
-
"Credential, keychain, or SSH material changes.",
|
|
74
|
-
],
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
const resolved = structuredClone(byProfile[profile]);
|
|
78
|
-
if (opts?.strictUnsafeConfirm === true) {
|
|
79
|
-
const extra = "Network actions when approvals are disabled.";
|
|
80
|
-
if (!resolved.unsafe_actions_requiring_explicit_user_ok.includes(extra)) {
|
|
81
|
-
resolved.unsafe_actions_requiring_explicit_user_ok.push(extra);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return resolved;
|
|
85
|
-
}
|
|
86
21
|
function parseBooleanValueForInit(flag, value) {
|
|
87
22
|
const normalized = value.trim().toLowerCase();
|
|
88
23
|
if (["1", "true", "yes", "y", "on"].includes(normalized))
|
|
@@ -410,7 +345,7 @@ async function cmdInit(opts) {
|
|
|
410
345
|
force: flags.force === true,
|
|
411
346
|
});
|
|
412
347
|
await ensureAgentplaneDirs(resolved.agentplaneDir, backend);
|
|
413
|
-
const execution =
|
|
348
|
+
const execution = buildExecutionProfile(executionProfile, { strictUnsafeConfirm });
|
|
414
349
|
await writeInitConfig({
|
|
415
350
|
agentplaneDir: resolved.agentplaneDir,
|
|
416
351
|
gitRoot: resolved.gitRoot,
|
|
@@ -432,6 +367,9 @@ async function cmdInit(opts) {
|
|
|
432
367
|
configPathAbs: configPath,
|
|
433
368
|
backendPathAbs: backendPath,
|
|
434
369
|
});
|
|
370
|
+
if (backend === "redmine") {
|
|
371
|
+
installPaths.push(".env.example");
|
|
372
|
+
}
|
|
435
373
|
await ensureInitGitignore({
|
|
436
374
|
gitRoot: resolved.gitRoot,
|
|
437
375
|
includeAgentPromptFiles: flags.gitignoreAgents === true,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-cli.d.ts","sourceRoot":"","sources":["../../src/cli/run-cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run-cli.d.ts","sourceRoot":"","sources":["../../src/cli/run-cli.ts"],"names":[],"mappings":"AAoWA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CA0K5D"}
|
package/dist/cli/run-cli.js
CHANGED
|
@@ -9,6 +9,7 @@ import { loadDotEnv } from "../shared/env.js";
|
|
|
9
9
|
import { CliError, formatJsonError } from "../shared/errors.js";
|
|
10
10
|
import { resolveContext } from "../usecases/context/resolve-context.js";
|
|
11
11
|
import { getVersion } from "../meta/version.js";
|
|
12
|
+
import { getApprovalRequirements } from "../commands/shared/approval-requirements.js";
|
|
12
13
|
import { parseCommandArgv } from "./spec/parse.js";
|
|
13
14
|
import { helpSpec } from "./spec/help.js";
|
|
14
15
|
import { usageError } from "./spec/errors.js";
|
|
@@ -375,7 +376,10 @@ export async function runCli(argv) {
|
|
|
375
376
|
if (resolved && matched?.entry.needsConfig !== false) {
|
|
376
377
|
try {
|
|
377
378
|
const loaded = await getLoadedConfig("update-check");
|
|
378
|
-
const requireNetwork =
|
|
379
|
+
const requireNetwork = getApprovalRequirements({
|
|
380
|
+
config: loaded.config,
|
|
381
|
+
action: "network_access",
|
|
382
|
+
}).required;
|
|
379
383
|
const explicitlyApproved = globals.allowNetwork;
|
|
380
384
|
skipUpdateCheckForPolicy = requireNetwork && !explicitlyApproved;
|
|
381
385
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run-cli.test-helpers.d.ts","sourceRoot":"","sources":["../../src/cli/run-cli.test-helpers.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"run-cli.test-helpers.d.ts","sourceRoot":"","sources":["../../src/cli/run-cli.test-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,11 +6,12 @@ import path from "node:path";
|
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import { promisify } from "node:util";
|
|
8
8
|
import { gzipSync } from "node:zlib";
|
|
9
|
-
import { afterAll, beforeAll } from "vitest";
|
|
9
|
+
import { afterAll, afterEach, beforeAll } from "vitest";
|
|
10
10
|
import { defaultConfig } from "@agentplaneorg/core";
|
|
11
11
|
import { runCli } from "./run-cli.js";
|
|
12
12
|
const execFileAsync = promisify(execFile);
|
|
13
13
|
let agentplaneHome = null;
|
|
14
|
+
const testRoots = new Set();
|
|
14
15
|
const originalAgentplaneHome = process.env.AGENTPLANE_HOME;
|
|
15
16
|
const originalNoUpdateCheck = process.env.AGENTPLANE_NO_UPDATE_CHECK;
|
|
16
17
|
const originalGitAuthorName = process.env.GIT_AUTHOR_NAME;
|
|
@@ -88,6 +89,14 @@ export function registerAgentplaneHome() {
|
|
|
88
89
|
else
|
|
89
90
|
process.env.GIT_COMMITTER_EMAIL = originalGitCommitterEmail;
|
|
90
91
|
});
|
|
92
|
+
afterEach(async () => {
|
|
93
|
+
const roots = [...testRoots];
|
|
94
|
+
testRoots.clear();
|
|
95
|
+
await Promise.all(roots.map(async (root) => {
|
|
96
|
+
await rm(path.join(root, ".agentplane", ".upgrade"), { recursive: true, force: true });
|
|
97
|
+
await rm(path.join(root, ".agentplane", ".release"), { recursive: true, force: true });
|
|
98
|
+
}));
|
|
99
|
+
});
|
|
91
100
|
}
|
|
92
101
|
export function getAgentplaneHome() {
|
|
93
102
|
return agentplaneHome;
|
|
@@ -154,10 +163,13 @@ export async function mkGitRepoRoot() {
|
|
|
154
163
|
const template = await ensureGitTemplateRoot();
|
|
155
164
|
const root = await mkdtemp(path.join(os.tmpdir(), "agentplane-cli-test-"));
|
|
156
165
|
await copyDirContents(template, root);
|
|
166
|
+
testRoots.add(root);
|
|
157
167
|
return root;
|
|
158
168
|
}
|
|
159
169
|
export async function mkTempDir() {
|
|
160
|
-
|
|
170
|
+
const root = await mkdtemp(path.join(os.tmpdir(), "agentplane-cli-test-"));
|
|
171
|
+
testRoots.add(root);
|
|
172
|
+
return root;
|
|
161
173
|
}
|
|
162
174
|
export async function writeDefaultConfig(root) {
|
|
163
175
|
const agentplaneDir = path.join(root, ".agentplane");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ansi.d.ts","sourceRoot":"","sources":["../../../src/cli/shared/ansi.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAa9C;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/C"}
|