@gh-symphony/cli 0.1.2 → 0.1.3
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/{chunk-WM2B6BJ7.js → chunk-2YF7PQUC.js} +1 -1
- package/dist/{chunk-DLZAJXZL.js → chunk-HQ7A3C7K.js} +1 -1
- package/dist/{chunk-B4ZJMAZL.js → chunk-NESHTYXQ.js} +3 -3
- package/dist/{chunk-VFHMHHZW.js → chunk-PEZUBHWJ.js} +1 -1
- package/dist/{chunk-GHVDABFO.js → chunk-PG332ZS4.js} +4 -1
- package/dist/{chunk-GPRCOJDJ.js → chunk-WCOIVNHH.js} +55 -7
- package/dist/{doctor-EEPNFCGF.js → doctor-2AXHIEAP.js} +4 -4
- package/dist/index.js +6 -6
- package/dist/{repo-RX4OK7XH.js → repo-SUXYT4OK.js} +338 -5
- package/dist/{setup-XNHHRBGU.js → setup-UBHOMXUG.js} +3 -3
- package/dist/{upgrade-NS53EO2B.js → upgrade-355SQJ5P.js} +2 -2
- package/dist/{version-2RHFZ5CI.js → version-4ILSDZQH.js} +1 -1
- package/dist/worker-entry.js +2 -2
- package/dist/{workflow-26QNZZWH.js → workflow-S6YSZPQT.js} +4 -4
- package/package.json +4 -4
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
workflow_init_default
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-2YF7PQUC.js";
|
|
5
5
|
import {
|
|
6
6
|
fetchGithubProjectIssueByRepositoryAndNumber,
|
|
7
7
|
inspectManagedProjectSelection
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-HQ7A3C7K.js";
|
|
9
9
|
import {
|
|
10
10
|
GitHubApiError,
|
|
11
11
|
createClient,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
buildPromptVariables,
|
|
19
19
|
parseWorkflowMarkdown,
|
|
20
20
|
renderPrompt
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-WCOIVNHH.js";
|
|
22
22
|
|
|
23
23
|
// src/commands/workflow.ts
|
|
24
24
|
import { readFile } from "fs/promises";
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-6I753NYO.js";
|
|
5
5
|
import {
|
|
6
6
|
parseWorkflowMarkdown
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-WCOIVNHH.js";
|
|
8
8
|
import {
|
|
9
9
|
saveGlobalConfig,
|
|
10
10
|
saveProjectConfig
|
|
@@ -63,6 +63,8 @@ async function initRepoRuntime(flags) {
|
|
|
63
63
|
const trackerBindingId = workflow.tracker.projectId ?? workflow.tracker.projectSlug ?? "";
|
|
64
64
|
const trackerSettings = {
|
|
65
65
|
...workflow.tracker.projectId ? { projectId: workflow.tracker.projectId } : {},
|
|
66
|
+
...workflow.tracker.projectSlug ? { projectSlug: workflow.tracker.projectSlug } : {},
|
|
67
|
+
...trackerAdapter === "linear" ? { activeStates: workflow.tracker.activeStates.join("\n") } : {},
|
|
66
68
|
repository: `${repository.owner}/${repository.name}`
|
|
67
69
|
};
|
|
68
70
|
if (flags.assignedOnly) {
|
|
@@ -85,6 +87,7 @@ async function initRepoRuntime(flags) {
|
|
|
85
87
|
tracker: {
|
|
86
88
|
adapter: trackerAdapter,
|
|
87
89
|
bindingId: trackerBindingId,
|
|
90
|
+
...workflow.tracker.endpoint ? { apiUrl: workflow.tracker.endpoint } : {},
|
|
88
91
|
settings: trackerSettings
|
|
89
92
|
}
|
|
90
93
|
};
|
|
@@ -25,6 +25,7 @@ function normalizeWorkflowState(state) {
|
|
|
25
25
|
var DEFAULT_CODEX_COMMAND = "codex app-server";
|
|
26
26
|
var DEFAULT_CLAUDE_COMMAND = "claude";
|
|
27
27
|
var DEFAULT_AGENT_COMMAND = DEFAULT_CODEX_COMMAND;
|
|
28
|
+
var DEFAULT_LINEAR_GRAPHQL_URL = "https://api.linear.app/graphql";
|
|
28
29
|
var DEFAULT_HOOK_TIMEOUT_MS = 6e4;
|
|
29
30
|
var DEFAULT_POLL_INTERVAL_MS = 3e4;
|
|
30
31
|
var DEFAULT_MAX_RETRY_BACKOFF_MS = 3e5;
|
|
@@ -129,6 +130,7 @@ function parseWorkflowMarkdown(markdown, env = process.env, options = {}) {
|
|
|
129
130
|
const hasRuntime = runtimeNode !== null;
|
|
130
131
|
const codex = hasRuntime ? readObject(frontMatter, "codex") : readRequiredObject(frontMatter, "codex");
|
|
131
132
|
const trackerKind = readRequiredString(tracker, "kind", env);
|
|
133
|
+
validateTrackerConfig(tracker, trackerKind, env);
|
|
132
134
|
const activeStates = readStringList(tracker, "active_states") ?? DEFAULT_WORKFLOW_TRACKER.activeStates;
|
|
133
135
|
const terminalStates = readStringList(tracker, "terminal_states") ?? DEFAULT_WORKFLOW_TRACKER.terminalStates;
|
|
134
136
|
const blockerCheckStates = readStringList(tracker, "blocker_check_states") ?? DEFAULT_WORKFLOW_TRACKER.blockerCheckStates;
|
|
@@ -160,7 +162,7 @@ function parseWorkflowMarkdown(markdown, env = process.env, options = {}) {
|
|
|
160
162
|
),
|
|
161
163
|
tracker: {
|
|
162
164
|
kind: trackerKind,
|
|
163
|
-
endpoint: readOptionalString(tracker, "endpoint", env),
|
|
165
|
+
endpoint: readOptionalString(tracker, "endpoint", env) ?? (trackerKind === "linear" ? DEFAULT_LINEAR_GRAPHQL_URL : null),
|
|
164
166
|
apiKey: readOptionalString(tracker, "api_key", env),
|
|
165
167
|
projectSlug: readOptionalString(tracker, "project_slug", env),
|
|
166
168
|
activeStates,
|
|
@@ -207,6 +209,32 @@ function parseWorkflowMarkdown(markdown, env = process.env, options = {}) {
|
|
|
207
209
|
};
|
|
208
210
|
return parsed;
|
|
209
211
|
}
|
|
212
|
+
function validateTrackerConfig(tracker, trackerKind, env) {
|
|
213
|
+
if (trackerKind !== "linear") {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
for (const key of ["project_id", "projectId", "teamId", "team_id"]) {
|
|
217
|
+
if (key in tracker) {
|
|
218
|
+
throw new Error(
|
|
219
|
+
`Workflow front matter field "tracker.${key}" is not supported for tracker.kind "linear"; use "tracker.project_slug".`
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const projectSlug = readOptionalString(tracker, "project_slug", env);
|
|
224
|
+
if (!projectSlug || projectSlug.trim().length === 0) {
|
|
225
|
+
throw new Error(
|
|
226
|
+
'Workflow front matter field "tracker.project_slug" is required for tracker.kind "linear".'
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
if ("endpoint" in tracker) {
|
|
230
|
+
const endpoint = readOptionalString(tracker, "endpoint", env);
|
|
231
|
+
if (!endpoint || endpoint.trim().length === 0) {
|
|
232
|
+
throw new Error(
|
|
233
|
+
'Workflow front matter field "tracker.endpoint" must be a non-empty string when provided for tracker.kind "linear".'
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
210
238
|
function parseLegacyWorkflowMarkdown(markdown) {
|
|
211
239
|
const promptGuidelines = matchOptionalSection(markdown, "Prompt Guidelines") ?? "";
|
|
212
240
|
return {
|
|
@@ -372,7 +400,9 @@ function splitInlineArrayEntries(inner) {
|
|
|
372
400
|
current += char;
|
|
373
401
|
}
|
|
374
402
|
if (quote) {
|
|
375
|
-
throw new Error(
|
|
403
|
+
throw new Error(
|
|
404
|
+
"Workflow front matter inline array has an unterminated string."
|
|
405
|
+
);
|
|
376
406
|
}
|
|
377
407
|
pushInlineArrayEntry(entries, current, "end");
|
|
378
408
|
return entries;
|
|
@@ -564,6 +594,16 @@ function resolveEnvironmentValue(value, env) {
|
|
|
564
594
|
}
|
|
565
595
|
return resolved;
|
|
566
596
|
}
|
|
597
|
+
const dollarEnvTokenMatch = value.match(/^\$([A-Z0-9_]+)$/);
|
|
598
|
+
if (dollarEnvTokenMatch) {
|
|
599
|
+
const resolved = env[dollarEnvTokenMatch[1]];
|
|
600
|
+
if (!resolved) {
|
|
601
|
+
throw new Error(
|
|
602
|
+
`Workflow front matter requires environment variable ${dollarEnvTokenMatch[1]}.`
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
return resolved;
|
|
606
|
+
}
|
|
567
607
|
return value.replace(/\$\{([A-Z0-9_]+)\}/g, (_, name) => {
|
|
568
608
|
const resolved = env[name];
|
|
569
609
|
if (!resolved) {
|
|
@@ -2188,15 +2228,18 @@ function createGitHubGraphQLMcpServerEntry(options = {}) {
|
|
|
2188
2228
|
// ../runtime-claude/src/mcp-compose.ts
|
|
2189
2229
|
async function composeClaudeMcpConfig(workspaceRoot, strictMode, symphonyTokenEnv = {}) {
|
|
2190
2230
|
const workspaceMcpPath = join3(workspaceRoot, ".mcp.json");
|
|
2191
|
-
const finalPath =
|
|
2231
|
+
const finalPath = resolveRuntimeMcpConfigPath(
|
|
2232
|
+
workspaceRoot,
|
|
2233
|
+
symphonyTokenEnv
|
|
2234
|
+
);
|
|
2192
2235
|
const baseConfig = await readBaseMcpConfig(workspaceMcpPath);
|
|
2193
2236
|
const mergedConfig = mergeGitHubGraphQLMcpServer(baseConfig, symphonyTokenEnv);
|
|
2194
2237
|
await mkdir(dirname(finalPath), { recursive: true });
|
|
2195
2238
|
await writeFile3(finalPath, JSON.stringify(mergedConfig, null, 2) + "\n", "utf8");
|
|
2196
2239
|
return {
|
|
2197
2240
|
finalPath,
|
|
2198
|
-
extraArgv: strictMode ? ["--strict-mcp-config", "--mcp-config", finalPath] : [],
|
|
2199
|
-
|
|
2241
|
+
extraArgv: strictMode ? ["--strict-mcp-config", "--mcp-config", finalPath] : ["--mcp-config", finalPath],
|
|
2242
|
+
cleanupPath: finalPath
|
|
2200
2243
|
};
|
|
2201
2244
|
}
|
|
2202
2245
|
async function readBaseMcpConfig(workspaceMcpPath) {
|
|
@@ -2228,9 +2271,13 @@ function mergeGitHubGraphQLMcpServer(baseConfig, env) {
|
|
|
2228
2271
|
}
|
|
2229
2272
|
};
|
|
2230
2273
|
}
|
|
2231
|
-
function
|
|
2274
|
+
function resolveRuntimeMcpConfigPath(workspaceRoot, env) {
|
|
2232
2275
|
const normalizedWorkspaceRoot = resolve4(workspaceRoot);
|
|
2233
|
-
const runtimeDir = env.WORKSPACE_RUNTIME_DIR ?? join3(
|
|
2276
|
+
const runtimeDir = env.WORKSPACE_RUNTIME_DIR ?? join3(
|
|
2277
|
+
dirname(normalizedWorkspaceRoot),
|
|
2278
|
+
".runtime",
|
|
2279
|
+
basename(normalizedWorkspaceRoot)
|
|
2280
|
+
);
|
|
2234
2281
|
return join3(runtimeDir, "mcp.json");
|
|
2235
2282
|
}
|
|
2236
2283
|
function isRecord3(value) {
|
|
@@ -3297,6 +3344,7 @@ export {
|
|
|
3297
3344
|
isStateActive,
|
|
3298
3345
|
isStateTerminal,
|
|
3299
3346
|
matchesWorkflowState,
|
|
3347
|
+
DEFAULT_LINEAR_GRAPHQL_URL,
|
|
3300
3348
|
DEFAULT_MAX_FAILURE_RETRIES,
|
|
3301
3349
|
resolveWorkflowRuntimeCommand,
|
|
3302
3350
|
resolveWorkflowRuntimeTimeouts,
|
|
@@ -3,13 +3,13 @@ import {
|
|
|
3
3
|
parseIssueReference,
|
|
4
4
|
readGitHubProjectBinding,
|
|
5
5
|
renderIssueWorkflowPreview
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
6
|
+
} from "./chunk-NESHTYXQ.js";
|
|
7
|
+
import "./chunk-2YF7PQUC.js";
|
|
8
8
|
import {
|
|
9
9
|
fetchGithubProjectIssueByRepositoryAndNumber,
|
|
10
10
|
fetchGithubProjectIssues,
|
|
11
11
|
inspectManagedProjectSelection
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-HQ7A3C7K.js";
|
|
13
13
|
import {
|
|
14
14
|
resolveRuntimeRoot
|
|
15
15
|
} from "./chunk-6I753NYO.js";
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
resolveClaudeCommandBinary,
|
|
35
35
|
resolveRuntimeCommandBinary,
|
|
36
36
|
runClaudePreflight
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-WCOIVNHH.js";
|
|
38
38
|
import "./chunk-WOVNN5NW.js";
|
|
39
39
|
|
|
40
40
|
// src/commands/doctor.ts
|
package/dist/index.js
CHANGED
|
@@ -414,13 +414,13 @@ function createRemovedCommandHandler(message) {
|
|
|
414
414
|
|
|
415
415
|
// src/index.ts
|
|
416
416
|
var COMMANDS = {
|
|
417
|
-
workflow: () => import("./workflow-
|
|
418
|
-
setup: () => import("./setup-
|
|
419
|
-
doctor: () => import("./doctor-
|
|
420
|
-
upgrade: () => import("./upgrade-
|
|
421
|
-
repo: () => import("./repo-
|
|
417
|
+
workflow: () => import("./workflow-S6YSZPQT.js"),
|
|
418
|
+
setup: () => import("./setup-UBHOMXUG.js"),
|
|
419
|
+
doctor: () => import("./doctor-2AXHIEAP.js"),
|
|
420
|
+
upgrade: () => import("./upgrade-355SQJ5P.js"),
|
|
421
|
+
repo: () => import("./repo-SUXYT4OK.js"),
|
|
422
422
|
config: () => import("./config-cmd-2ADPUYWA.js"),
|
|
423
|
-
version: () => import("./version-
|
|
423
|
+
version: () => import("./version-4ILSDZQH.js")
|
|
424
424
|
};
|
|
425
425
|
function addGlobalOptions(command) {
|
|
426
426
|
return command.option("--config <dir>", "Config directory").addOption(new Option("--config-dir <dir>").hideHelp()).option("-v, --verbose", "Enable verbose output").option("--json", "Output in JSON format").option("--no-color", "Disable color output");
|
|
@@ -14,17 +14,17 @@ import {
|
|
|
14
14
|
stripAnsi,
|
|
15
15
|
yellow
|
|
16
16
|
} from "./chunk-MVRF7BES.js";
|
|
17
|
-
import "./chunk-
|
|
17
|
+
import "./chunk-PEZUBHWJ.js";
|
|
18
18
|
import {
|
|
19
19
|
initRepoRuntime,
|
|
20
20
|
parseRepoRuntimeFlags
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-PG332ZS4.js";
|
|
22
22
|
import {
|
|
23
23
|
findGithubProjectIssue,
|
|
24
24
|
handleMissingManagedProjectConfig,
|
|
25
25
|
resolveManagedProjectConfig,
|
|
26
26
|
resolveTrackerAdapter
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-HQ7A3C7K.js";
|
|
28
28
|
import {
|
|
29
29
|
resolveRepoRuntimeRoot,
|
|
30
30
|
resolveRuntimeRoot
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
getGhToken
|
|
35
35
|
} from "./chunk-Z3NZOPLZ.js";
|
|
36
36
|
import {
|
|
37
|
+
DEFAULT_LINEAR_GRAPHQL_URL,
|
|
37
38
|
DEFAULT_MAX_FAILURE_RETRIES,
|
|
38
39
|
DEFAULT_WORKFLOW_LIFECYCLE,
|
|
39
40
|
WorkflowConfigStore,
|
|
@@ -62,7 +63,7 @@ import {
|
|
|
62
63
|
resolveWorkflowRuntimeTimeouts,
|
|
63
64
|
safeReadDir,
|
|
64
65
|
scheduleRetryAt
|
|
65
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-WCOIVNHH.js";
|
|
66
67
|
import {
|
|
67
68
|
daemonPidPath,
|
|
68
69
|
httpStatusPath,
|
|
@@ -1076,9 +1077,341 @@ var fileTrackerAdapter = {
|
|
|
1076
1077
|
}
|
|
1077
1078
|
};
|
|
1078
1079
|
|
|
1080
|
+
// ../tracker-linear/src/orchestrator-adapter.ts
|
|
1081
|
+
var DEFAULT_LINEAR_GRAPHQL_URL2 = DEFAULT_LINEAR_GRAPHQL_URL;
|
|
1082
|
+
var DEFAULT_PAGE_SIZE = 50;
|
|
1083
|
+
var LINEAR_IDENTIFIER_PATTERN = /^[A-Z][A-Z0-9]*-\d+$/;
|
|
1084
|
+
var LINEAR_ISSUE_FIELDS = (
|
|
1085
|
+
/* GraphQL */
|
|
1086
|
+
`
|
|
1087
|
+
nodes {
|
|
1088
|
+
id
|
|
1089
|
+
identifier
|
|
1090
|
+
number
|
|
1091
|
+
title
|
|
1092
|
+
description
|
|
1093
|
+
priority
|
|
1094
|
+
url
|
|
1095
|
+
createdAt
|
|
1096
|
+
updatedAt
|
|
1097
|
+
state {
|
|
1098
|
+
name
|
|
1099
|
+
}
|
|
1100
|
+
labels {
|
|
1101
|
+
nodes {
|
|
1102
|
+
name
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
relations {
|
|
1106
|
+
nodes {
|
|
1107
|
+
type
|
|
1108
|
+
relatedIssue {
|
|
1109
|
+
id
|
|
1110
|
+
identifier
|
|
1111
|
+
state {
|
|
1112
|
+
name
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
pageInfo {
|
|
1119
|
+
hasNextPage
|
|
1120
|
+
endCursor
|
|
1121
|
+
}
|
|
1122
|
+
`
|
|
1123
|
+
);
|
|
1124
|
+
var LINEAR_ISSUES_BY_STATES_QUERY = (
|
|
1125
|
+
/* GraphQL */
|
|
1126
|
+
`
|
|
1127
|
+
query SymphonyLinearIssues(
|
|
1128
|
+
$projectSlug: String!
|
|
1129
|
+
$stateNames: [String!]!
|
|
1130
|
+
$first: Int!
|
|
1131
|
+
$after: String
|
|
1132
|
+
) {
|
|
1133
|
+
issues(
|
|
1134
|
+
first: $first
|
|
1135
|
+
after: $after
|
|
1136
|
+
filter: {
|
|
1137
|
+
project: { slugId: { eq: $projectSlug } }
|
|
1138
|
+
state: { name: { in: $stateNames } }
|
|
1139
|
+
}
|
|
1140
|
+
) {
|
|
1141
|
+
${LINEAR_ISSUE_FIELDS}
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
`
|
|
1145
|
+
);
|
|
1146
|
+
var LINEAR_ISSUES_BY_IDS_QUERY = (
|
|
1147
|
+
/* GraphQL */
|
|
1148
|
+
`
|
|
1149
|
+
query SymphonyLinearIssueStates(
|
|
1150
|
+
$projectSlug: String!
|
|
1151
|
+
$issueIds: [ID!]!
|
|
1152
|
+
$first: Int!
|
|
1153
|
+
$after: String
|
|
1154
|
+
) {
|
|
1155
|
+
issues(
|
|
1156
|
+
first: $first
|
|
1157
|
+
after: $after
|
|
1158
|
+
filter: {
|
|
1159
|
+
project: { slugId: { eq: $projectSlug } }
|
|
1160
|
+
id: { in: $issueIds }
|
|
1161
|
+
}
|
|
1162
|
+
) {
|
|
1163
|
+
${LINEAR_ISSUE_FIELDS}
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
`
|
|
1167
|
+
);
|
|
1168
|
+
var linearTrackerAdapter = {
|
|
1169
|
+
async listIssues(project, dependencies = {}) {
|
|
1170
|
+
return listLinearIssues(
|
|
1171
|
+
project,
|
|
1172
|
+
project.tracker.settings?.activeStates,
|
|
1173
|
+
dependencies
|
|
1174
|
+
);
|
|
1175
|
+
},
|
|
1176
|
+
async listIssuesByStates(project, states, dependencies = {}) {
|
|
1177
|
+
if (states.length === 0) {
|
|
1178
|
+
return [];
|
|
1179
|
+
}
|
|
1180
|
+
return listLinearIssues(project, states, dependencies);
|
|
1181
|
+
},
|
|
1182
|
+
async fetchIssueStatesByIds(project, issueIds, dependencies = {}) {
|
|
1183
|
+
if (issueIds.length === 0) {
|
|
1184
|
+
return [];
|
|
1185
|
+
}
|
|
1186
|
+
return listLinearIssues(project, void 0, dependencies, issueIds);
|
|
1187
|
+
},
|
|
1188
|
+
buildWorkerEnvironment(project, issue) {
|
|
1189
|
+
return {
|
|
1190
|
+
LINEAR_GRAPHQL_URL: resolveLinearEndpoint(project.tracker),
|
|
1191
|
+
LINEAR_ISSUE_ID: issue.id,
|
|
1192
|
+
LINEAR_ISSUE_IDENTIFIER: issue.identifier,
|
|
1193
|
+
SYMPHONY_TRACKER_KIND: "linear"
|
|
1194
|
+
};
|
|
1195
|
+
},
|
|
1196
|
+
reviveIssue(project, run) {
|
|
1197
|
+
const revivedIdentifier = reviveLinearIdentifier(run.issueIdentifier);
|
|
1198
|
+
return {
|
|
1199
|
+
id: run.issueId,
|
|
1200
|
+
identifier: revivedIdentifier,
|
|
1201
|
+
number: parseLinearIssueNumberOrZero(revivedIdentifier),
|
|
1202
|
+
title: run.issueTitle ?? run.issueIdentifier,
|
|
1203
|
+
description: null,
|
|
1204
|
+
priority: null,
|
|
1205
|
+
state: run.issueState,
|
|
1206
|
+
branchName: null,
|
|
1207
|
+
url: null,
|
|
1208
|
+
labels: [],
|
|
1209
|
+
blockedBy: [],
|
|
1210
|
+
createdAt: null,
|
|
1211
|
+
updatedAt: null,
|
|
1212
|
+
repository: project.repository,
|
|
1213
|
+
tracker: {
|
|
1214
|
+
adapter: "linear",
|
|
1215
|
+
bindingId: project.tracker.bindingId,
|
|
1216
|
+
itemId: run.issueId
|
|
1217
|
+
},
|
|
1218
|
+
metadata: {}
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
};
|
|
1222
|
+
async function listLinearIssues(project, stateNamesInput, dependencies, issueIds) {
|
|
1223
|
+
const config = resolveLinearTrackerConfig(project, dependencies);
|
|
1224
|
+
const client = createLinearGraphqlClient(config, dependencies.fetchImpl);
|
|
1225
|
+
const stateNames = readStringArray(stateNamesInput);
|
|
1226
|
+
if (!issueIds && (!stateNames || stateNames.length === 0)) {
|
|
1227
|
+
throw new Error(
|
|
1228
|
+
'Tracker adapter "linear" requires at least one active state name in the "activeStates" setting.'
|
|
1229
|
+
);
|
|
1230
|
+
}
|
|
1231
|
+
const nodes = await fetchPaginatedLinearIssues(client, {
|
|
1232
|
+
projectSlug: config.projectSlug,
|
|
1233
|
+
stateNames,
|
|
1234
|
+
issueIds: issueIds ? [...issueIds] : void 0,
|
|
1235
|
+
pageSize: config.pageSize
|
|
1236
|
+
});
|
|
1237
|
+
return nodes.map(
|
|
1238
|
+
(node) => normalizeLinearIssue(project, config.projectSlug, node)
|
|
1239
|
+
);
|
|
1240
|
+
}
|
|
1241
|
+
async function fetchPaginatedLinearIssues(client, input) {
|
|
1242
|
+
const issues = [];
|
|
1243
|
+
let after = null;
|
|
1244
|
+
do {
|
|
1245
|
+
const query = input.issueIds ? LINEAR_ISSUES_BY_IDS_QUERY : LINEAR_ISSUES_BY_STATES_QUERY;
|
|
1246
|
+
const response = await client(
|
|
1247
|
+
query,
|
|
1248
|
+
{
|
|
1249
|
+
projectSlug: input.projectSlug,
|
|
1250
|
+
...input.issueIds ? { issueIds: input.issueIds } : { stateNames: input.stateNames ?? [] },
|
|
1251
|
+
first: input.pageSize,
|
|
1252
|
+
after
|
|
1253
|
+
}
|
|
1254
|
+
);
|
|
1255
|
+
const connection = response.issues;
|
|
1256
|
+
issues.push(...connection?.nodes ?? []);
|
|
1257
|
+
after = connection?.pageInfo?.hasNextPage ? connection.pageInfo.endCursor ?? null : null;
|
|
1258
|
+
} while (after);
|
|
1259
|
+
return issues;
|
|
1260
|
+
}
|
|
1261
|
+
function normalizeLinearIssue(project, projectSlug, issue) {
|
|
1262
|
+
const id = requireString(issue.id, "Linear issue id");
|
|
1263
|
+
const identifier = sanitizeLinearIdentifier(
|
|
1264
|
+
requireString(issue.identifier, "Linear issue identifier")
|
|
1265
|
+
);
|
|
1266
|
+
const state = requireString(issue.state?.name, "Linear issue state name");
|
|
1267
|
+
return {
|
|
1268
|
+
id,
|
|
1269
|
+
identifier,
|
|
1270
|
+
number: typeof issue.number === "number" ? issue.number : parseLinearIssueNumber(identifier),
|
|
1271
|
+
title: issue.title ?? identifier,
|
|
1272
|
+
description: issue.description ?? null,
|
|
1273
|
+
priority: typeof issue.priority === "number" ? issue.priority : null,
|
|
1274
|
+
state,
|
|
1275
|
+
branchName: null,
|
|
1276
|
+
url: issue.url ?? null,
|
|
1277
|
+
labels: (issue.labels?.nodes ?? []).map((label) => label.name).filter((label) => typeof label === "string"),
|
|
1278
|
+
blockedBy: (issue.relations?.nodes ?? []).filter((relation) => relation.type === "blocks").map((relation) => ({
|
|
1279
|
+
id: relation.relatedIssue?.id ?? null,
|
|
1280
|
+
identifier: typeof relation.relatedIssue?.identifier === "string" ? sanitizeLinearIdentifier(relation.relatedIssue.identifier) : null,
|
|
1281
|
+
state: relation.relatedIssue?.state?.name ?? null
|
|
1282
|
+
})),
|
|
1283
|
+
createdAt: issue.createdAt ?? null,
|
|
1284
|
+
updatedAt: issue.updatedAt ?? null,
|
|
1285
|
+
repository: project.repository,
|
|
1286
|
+
tracker: {
|
|
1287
|
+
adapter: "linear",
|
|
1288
|
+
bindingId: project.tracker.bindingId,
|
|
1289
|
+
itemId: id
|
|
1290
|
+
},
|
|
1291
|
+
metadata: {
|
|
1292
|
+
projectSlug
|
|
1293
|
+
}
|
|
1294
|
+
};
|
|
1295
|
+
}
|
|
1296
|
+
function createLinearGraphqlClient(config, fetchImpl = fetch) {
|
|
1297
|
+
return async (query, variables) => {
|
|
1298
|
+
const response = await fetchImpl(config.endpoint, {
|
|
1299
|
+
method: "POST",
|
|
1300
|
+
headers: {
|
|
1301
|
+
"Content-Type": "application/json",
|
|
1302
|
+
Authorization: config.token
|
|
1303
|
+
},
|
|
1304
|
+
body: JSON.stringify({ query, variables })
|
|
1305
|
+
});
|
|
1306
|
+
if (!response.ok) {
|
|
1307
|
+
throw new Error(
|
|
1308
|
+
`Linear GraphQL request failed with HTTP ${response.status}.`
|
|
1309
|
+
);
|
|
1310
|
+
}
|
|
1311
|
+
const payload = await response.json();
|
|
1312
|
+
if (payload.errors?.length) {
|
|
1313
|
+
const message = payload.errors.map((error) => error.message).filter(Boolean).join("; ") || "Unknown Linear GraphQL error";
|
|
1314
|
+
throw new Error(`Linear GraphQL request failed: ${message}`);
|
|
1315
|
+
}
|
|
1316
|
+
if (!payload.data) {
|
|
1317
|
+
throw new Error("Linear GraphQL response did not include data.");
|
|
1318
|
+
}
|
|
1319
|
+
return payload.data;
|
|
1320
|
+
};
|
|
1321
|
+
}
|
|
1322
|
+
function resolveLinearTrackerConfig(project, dependencies) {
|
|
1323
|
+
const projectSlug = readRequiredSetting(project.tracker, "projectSlug");
|
|
1324
|
+
const token = dependencies.token ?? process.env.LINEAR_API_KEY;
|
|
1325
|
+
if (!token) {
|
|
1326
|
+
throw new Error("LINEAR_API_KEY environment variable is required.");
|
|
1327
|
+
}
|
|
1328
|
+
return {
|
|
1329
|
+
endpoint: resolveLinearEndpoint(project.tracker),
|
|
1330
|
+
pageSize: readPositiveIntegerSetting(project.tracker, "pageSize") ?? DEFAULT_PAGE_SIZE,
|
|
1331
|
+
projectSlug,
|
|
1332
|
+
token
|
|
1333
|
+
};
|
|
1334
|
+
}
|
|
1335
|
+
function resolveLinearEndpoint(tracker) {
|
|
1336
|
+
return tracker.apiUrl?.trim() || DEFAULT_LINEAR_GRAPHQL_URL2;
|
|
1337
|
+
}
|
|
1338
|
+
function readRequiredSetting(tracker, key) {
|
|
1339
|
+
const value = tracker.settings?.[key];
|
|
1340
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
1341
|
+
throw new Error(
|
|
1342
|
+
`Tracker adapter "${tracker.adapter}" requires the "${key}" setting.`
|
|
1343
|
+
);
|
|
1344
|
+
}
|
|
1345
|
+
return value;
|
|
1346
|
+
}
|
|
1347
|
+
function readPositiveIntegerSetting(tracker, key) {
|
|
1348
|
+
const value = tracker.settings?.[key];
|
|
1349
|
+
if (value === void 0) {
|
|
1350
|
+
return void 0;
|
|
1351
|
+
}
|
|
1352
|
+
if (typeof value === "number" && Number.isInteger(value) && value > 0) {
|
|
1353
|
+
return value;
|
|
1354
|
+
}
|
|
1355
|
+
if (typeof value === "string") {
|
|
1356
|
+
const parsed = Number(value);
|
|
1357
|
+
if (Number.isInteger(parsed) && parsed > 0) {
|
|
1358
|
+
return parsed;
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
throw new Error(
|
|
1362
|
+
`Tracker adapter "${tracker.adapter}" requires the "${key}" setting to be a positive integer when provided.`
|
|
1363
|
+
);
|
|
1364
|
+
}
|
|
1365
|
+
function readStringArray(value) {
|
|
1366
|
+
if (value === void 0) {
|
|
1367
|
+
return void 0;
|
|
1368
|
+
}
|
|
1369
|
+
if (typeof value === "string") {
|
|
1370
|
+
return value.split(/\r?\n|,/).map((entry) => entry.trim()).filter(Boolean);
|
|
1371
|
+
}
|
|
1372
|
+
if (!Array.isArray(value)) {
|
|
1373
|
+
return void 0;
|
|
1374
|
+
}
|
|
1375
|
+
return value.filter((entry) => typeof entry === "string");
|
|
1376
|
+
}
|
|
1377
|
+
function requireString(value, label) {
|
|
1378
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
1379
|
+
throw new Error(`${label} is required.`);
|
|
1380
|
+
}
|
|
1381
|
+
return value;
|
|
1382
|
+
}
|
|
1383
|
+
function sanitizeLinearIdentifier(identifier) {
|
|
1384
|
+
const sanitized = identifier.trim().toUpperCase();
|
|
1385
|
+
if (!LINEAR_IDENTIFIER_PATTERN.test(sanitized)) {
|
|
1386
|
+
throw new Error(
|
|
1387
|
+
`Linear issue identifier "${identifier}" must match ${LINEAR_IDENTIFIER_PATTERN.source}.`
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
return sanitized;
|
|
1391
|
+
}
|
|
1392
|
+
function parseLinearIssueNumber(identifier) {
|
|
1393
|
+
const sanitized = sanitizeLinearIdentifier(identifier);
|
|
1394
|
+
return Number.parseInt(sanitized.split("-").at(-1) ?? "0", 10);
|
|
1395
|
+
}
|
|
1396
|
+
function parseLinearIssueNumberOrZero(identifier) {
|
|
1397
|
+
try {
|
|
1398
|
+
return parseLinearIssueNumber(identifier);
|
|
1399
|
+
} catch {
|
|
1400
|
+
return 0;
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
function reviveLinearIdentifier(identifier) {
|
|
1404
|
+
try {
|
|
1405
|
+
return sanitizeLinearIdentifier(identifier);
|
|
1406
|
+
} catch {
|
|
1407
|
+
return identifier;
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1079
1411
|
// ../orchestrator/src/tracker-adapters.ts
|
|
1080
1412
|
var localAdapters = /* @__PURE__ */ new Map([
|
|
1081
|
-
["file", fileTrackerAdapter]
|
|
1413
|
+
["file", fileTrackerAdapter],
|
|
1414
|
+
["linear", linearTrackerAdapter]
|
|
1082
1415
|
]);
|
|
1083
1416
|
function resolveTrackerAdapter2(tracker) {
|
|
1084
1417
|
const local = localAdapters.get(tracker.adapter);
|
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
validateStateMapping,
|
|
11
11
|
writeEcosystem,
|
|
12
12
|
writeWorkflowPlan
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-2YF7PQUC.js";
|
|
14
14
|
import {
|
|
15
15
|
initRepoRuntime
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-PG332ZS4.js";
|
|
17
17
|
import "./chunk-6I753NYO.js";
|
|
18
18
|
import {
|
|
19
19
|
GhAuthError,
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
listUserProjects,
|
|
27
27
|
validateToken
|
|
28
28
|
} from "./chunk-Z3NZOPLZ.js";
|
|
29
|
-
import "./chunk-
|
|
29
|
+
import "./chunk-WCOIVNHH.js";
|
|
30
30
|
import "./chunk-WOVNN5NW.js";
|
|
31
31
|
|
|
32
32
|
// src/commands/setup.ts
|
|
@@ -16,8 +16,8 @@ function execFileAsync(file, args, execFileImpl = execFileCallback) {
|
|
|
16
16
|
});
|
|
17
17
|
}
|
|
18
18
|
function resolveCurrentCliVersion() {
|
|
19
|
-
if ("0.1.
|
|
20
|
-
return "0.1.
|
|
19
|
+
if ("0.1.3".length > 0) {
|
|
20
|
+
return "0.1.3";
|
|
21
21
|
}
|
|
22
22
|
const pkg = JSON.parse(
|
|
23
23
|
readFileSync(new URL("../../package.json", import.meta.url), "utf8")
|
package/dist/worker-entry.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
normalizeCodexRuntimeEvents,
|
|
7
7
|
prepareCodexRuntimePlan,
|
|
8
8
|
resolveLocalRuntimeLaunchConfig
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-PEZUBHWJ.js";
|
|
10
10
|
import {
|
|
11
11
|
DEFAULT_AGENT_INPUT_REQUIRED_REASON,
|
|
12
12
|
classifySessionExit,
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
resolveClaudeCommandBinary,
|
|
18
18
|
resolveWorkflowRuntimeCommand,
|
|
19
19
|
runClaudePreflight
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-WCOIVNHH.js";
|
|
21
21
|
|
|
22
22
|
// ../worker/src/index.ts
|
|
23
23
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -6,11 +6,11 @@ import {
|
|
|
6
6
|
resetWorkflowCommandDependenciesForTest,
|
|
7
7
|
setWorkflowCommandDependenciesForTest,
|
|
8
8
|
workflow_default
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-NESHTYXQ.js";
|
|
10
|
+
import "./chunk-2YF7PQUC.js";
|
|
11
|
+
import "./chunk-HQ7A3C7K.js";
|
|
12
12
|
import "./chunk-Z3NZOPLZ.js";
|
|
13
|
-
import "./chunk-
|
|
13
|
+
import "./chunk-WCOIVNHH.js";
|
|
14
14
|
import "./chunk-WOVNN5NW.js";
|
|
15
15
|
export {
|
|
16
16
|
workflow_default as default,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gh-symphony/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "hojinzs",
|
|
6
6
|
"description": "Interactive CLI for GitHub Symphony orchestration",
|
|
@@ -41,12 +41,12 @@
|
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"tsup": "^8.5.1",
|
|
44
|
-
"@gh-symphony/core": "0.0.14",
|
|
45
|
-
"@gh-symphony/dashboard": "0.0.14",
|
|
46
44
|
"@gh-symphony/control-plane": "0.0.15",
|
|
45
|
+
"@gh-symphony/dashboard": "0.0.14",
|
|
46
|
+
"@gh-symphony/core": "0.0.14",
|
|
47
47
|
"@gh-symphony/orchestrator": "0.0.14",
|
|
48
|
-
"@gh-symphony/runtime-claude": "0.0.14",
|
|
49
48
|
"@gh-symphony/worker": "0.0.14",
|
|
49
|
+
"@gh-symphony/runtime-claude": "0.0.14",
|
|
50
50
|
"@gh-symphony/tracker-github": "0.0.14"
|
|
51
51
|
},
|
|
52
52
|
"scripts": {
|