@gajae-code/coding-agent 0.2.1 → 0.2.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/CHANGELOG.md +59 -1
- package/dist/types/cli/setup-cli.d.ts +1 -0
- package/dist/types/commands/contribution-prep.d.ts +18 -0
- package/dist/types/commands/deep-interview.d.ts +41 -0
- package/dist/types/commands/session.d.ts +24 -0
- package/dist/types/commands/setup.d.ts +3 -0
- package/dist/types/config/model-registry.d.ts +2 -2
- package/dist/types/config/models-config-schema.d.ts +17 -9
- package/dist/types/config/settings-schema.d.ts +37 -24
- package/dist/types/discovery/helpers.d.ts +2 -0
- package/dist/types/extensibility/extensions/types.d.ts +6 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +33 -0
- package/dist/types/gjc-runtime/goal-mode-request.d.ts +1 -1
- package/dist/types/gjc-runtime/launch-tmux.d.ts +12 -11
- package/dist/types/gjc-runtime/ralplan-runtime.d.ts +25 -0
- package/dist/types/gjc-runtime/state-runtime.d.ts +13 -0
- package/dist/types/gjc-runtime/team-runtime.d.ts +37 -5
- package/dist/types/gjc-runtime/tmux-common.d.ts +41 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +17 -0
- package/dist/types/goals/runtime.d.ts +3 -9
- package/dist/types/goals/state.d.ts +3 -6
- package/dist/types/goals/tools/goal-tool.d.ts +1 -69
- package/dist/types/hooks/skill-state.d.ts +5 -0
- package/dist/types/memories/index.d.ts +1 -1
- package/dist/types/memory-backend/local-backend.d.ts +3 -3
- package/dist/types/modes/components/hook-selector.d.ts +7 -0
- package/dist/types/modes/components/settings-selector.d.ts +0 -2
- package/dist/types/modes/components/status-line/types.d.ts +0 -3
- package/dist/types/modes/components/status-line.d.ts +0 -3
- package/dist/types/modes/controllers/command-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -12
- package/dist/types/modes/theme/defaults/index.d.ts +0 -2
- package/dist/types/modes/theme/theme.d.ts +1 -2
- package/dist/types/modes/types.d.ts +1 -7
- package/dist/types/modes/utils/context-usage.d.ts +6 -2
- package/dist/types/sdk.d.ts +6 -2
- package/dist/types/session/agent-session.d.ts +47 -1
- package/dist/types/session/contribution-prep.d.ts +47 -0
- package/dist/types/session/session-manager.d.ts +3 -0
- package/dist/types/setup/model-onboarding-guidance.d.ts +1 -0
- package/dist/types/setup/provider-onboarding.d.ts +29 -5
- package/dist/types/skill-state/active-state.d.ts +30 -1
- package/dist/types/skill-state/deep-interview-mutation-guard.d.ts +6 -1
- package/dist/types/skill-state/initial-phase.d.ts +12 -0
- package/dist/types/skill-state/workflow-hud.d.ts +9 -4
- package/dist/types/skill-state/workflow-state-contract.d.ts +34 -0
- package/dist/types/task/executor.d.ts +2 -0
- package/dist/types/task/types.d.ts +11 -0
- package/dist/types/tools/index.d.ts +20 -1
- package/dist/types/tools/skill.d.ts +47 -0
- package/dist/types/utils/changelog.d.ts +18 -2
- package/package.json +7 -7
- package/src/cli/args.ts +3 -2
- package/src/cli/setup-cli.ts +26 -12
- package/src/cli.ts +7 -1
- package/src/commands/contribution-prep.ts +41 -0
- package/src/commands/deep-interview.ts +30 -23
- package/src/commands/launch.ts +10 -1
- package/src/commands/ralplan.ts +10 -22
- package/src/commands/session.ts +150 -0
- package/src/commands/setup.ts +2 -0
- package/src/commands/state.ts +15 -4
- package/src/commands/team.ts +23 -3
- package/src/config/model-registry.ts +10 -2
- package/src/config/models-config-schema.ts +120 -102
- package/src/config/settings-schema.ts +42 -25
- package/src/config.ts +1 -1
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +32 -13
- package/src/defaults/gjc/skills/ralplan/SKILL.md +22 -2
- package/src/defaults/gjc/skills/team/SKILL.md +39 -7
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +33 -25
- package/src/discovery/helpers.ts +24 -1
- package/src/eval/py/prelude.py +1 -1
- package/src/extensibility/extensions/types.ts +6 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +546 -0
- package/src/gjc-runtime/goal-mode-request.ts +2 -19
- package/src/gjc-runtime/launch-tmux.ts +83 -43
- package/src/gjc-runtime/ralplan-runtime.ts +460 -0
- package/src/gjc-runtime/state-runtime.ts +731 -0
- package/src/gjc-runtime/team-runtime.ts +708 -52
- package/src/gjc-runtime/tmux-common.ts +119 -0
- package/src/gjc-runtime/tmux-sessions.ts +165 -0
- package/src/gjc-runtime/ultragoal-guard.ts +6 -3
- package/src/gjc-runtime/ultragoal-runtime.ts +5 -4
- package/src/goals/runtime.ts +38 -144
- package/src/goals/state.ts +36 -7
- package/src/goals/tools/goal-tool.ts +15 -172
- package/src/hooks/skill-state.ts +39 -18
- package/src/internal-urls/docs-index.generated.ts +5 -4
- package/src/internal-urls/memory-protocol.ts +3 -2
- package/src/main.ts +2 -3
- package/src/memories/index.ts +2 -1
- package/src/memory-backend/local-backend.ts +14 -6
- package/src/modes/components/hook-selector.ts +156 -1
- package/src/modes/components/settings-selector.ts +5 -12
- package/src/modes/components/skill-hud/render.ts +4 -0
- package/src/modes/components/status-line/segments.ts +5 -16
- package/src/modes/components/status-line/types.ts +0 -3
- package/src/modes/components/status-line.ts +0 -6
- package/src/modes/controllers/command-controller.ts +27 -4
- package/src/modes/controllers/extension-ui-controller.ts +1 -0
- package/src/modes/controllers/input-controller.ts +0 -15
- package/src/modes/controllers/selector-controller.ts +4 -11
- package/src/modes/interactive-mode.ts +18 -219
- package/src/modes/theme/defaults/dark-poimandres.json +0 -1
- package/src/modes/theme/defaults/light-poimandres.json +0 -1
- package/src/modes/theme/theme.ts +0 -6
- package/src/modes/types.ts +1 -7
- package/src/modes/utils/context-usage.ts +66 -17
- package/src/prompts/agents/architect.md +3 -0
- package/src/prompts/agents/executor.md +2 -0
- package/src/prompts/agents/frontmatter.md +1 -0
- package/src/prompts/goals/goal-continuation.md +1 -4
- package/src/prompts/goals/goal-mode-active.md +3 -5
- package/src/prompts/system/subagent-system-prompt.md +6 -0
- package/src/prompts/system/system-prompt.md +5 -7
- package/src/prompts/tools/goal.md +4 -4
- package/src/prompts/tools/skill.md +28 -0
- package/src/prompts/tools/task.md +3 -0
- package/src/sdk.ts +51 -11
- package/src/session/agent-session.ts +222 -21
- package/src/session/contribution-prep.ts +320 -0
- package/src/session/session-manager.ts +9 -1
- package/src/setup/model-onboarding-guidance.ts +6 -3
- package/src/setup/provider-onboarding.ts +177 -16
- package/src/skill-state/active-state.ts +188 -25
- package/src/skill-state/deep-interview-mutation-guard.ts +72 -21
- package/src/skill-state/initial-phase.ts +17 -0
- package/src/skill-state/workflow-hud.ts +23 -5
- package/src/skill-state/workflow-state-contract.ts +121 -0
- package/src/slash-commands/builtin-registry.ts +75 -25
- package/src/slash-commands/helpers/context-report.ts +123 -13
- package/src/task/agents.ts +1 -0
- package/src/task/commands.ts +1 -5
- package/src/task/executor.ts +9 -1
- package/src/task/index.ts +91 -4
- package/src/task/types.ts +6 -0
- package/src/tools/ask.ts +2 -0
- package/src/tools/gh.ts +212 -2
- package/src/tools/index.ts +25 -6
- package/src/tools/skill.ts +153 -0
- package/src/utils/changelog.ts +67 -44
- package/dist/types/commands/gjc-runtime-bridge.d.ts +0 -30
- package/dist/types/commands/question.d.ts +0 -7
- package/dist/types/modes/loop-limit.d.ts +0 -22
- package/src/commands/gjc-runtime-bridge.ts +0 -227
- package/src/commands/question.ts +0 -12
- package/src/modes/loop-limit.ts +0 -140
- package/src/prompts/commands/orchestrate.md +0 -49
- package/src/prompts/goals/goal-budget-limit.md +0 -16
- package/src/prompts/tools/create-goal.md +0 -3
- package/src/prompts/tools/get-goal.md +0 -3
- package/src/prompts/tools/update-goal.md +0 -3
package/src/tools/gh.ts
CHANGED
|
@@ -225,6 +225,10 @@ const RUN_SUCCESS_CONCLUSIONS = new Set(["success", "neutral", "skipped"]);
|
|
|
225
225
|
const RUN_FAILURE_CONCLUSIONS = new Set(["failure", "timed_out", "cancelled", "action_required", "startup_failure"]);
|
|
226
226
|
const JOB_FAILURE_CONCLUSIONS = new Set(["failure", "timed_out", "cancelled", "action_required"]);
|
|
227
227
|
|
|
228
|
+
const PR_CREATE_BASE_CONFIG_KEYS = ["github.prBase", "gh.prBase", "gjc.github.prBase"] as const;
|
|
229
|
+
const ISSUE_CLOSING_REFERENCE_PATTERN =
|
|
230
|
+
/(?:close[sd]?|fix(?:e[sd])?|resolve[sd]?)\s+(?:https:\/\/github\.com\/([^\s/]+\/[^\s/]+)\/issues\/)?#(\d+)\b/gi;
|
|
231
|
+
|
|
228
232
|
const githubSchema = z
|
|
229
233
|
.object({
|
|
230
234
|
op: z
|
|
@@ -407,6 +411,23 @@ interface GhIssueViewData {
|
|
|
407
411
|
updatedAt?: string;
|
|
408
412
|
url?: string;
|
|
409
413
|
}
|
|
414
|
+
interface GhPrListData {
|
|
415
|
+
baseRefName?: string;
|
|
416
|
+
headRefName?: string;
|
|
417
|
+
isDraft?: boolean;
|
|
418
|
+
number?: number;
|
|
419
|
+
state?: string;
|
|
420
|
+
title?: string;
|
|
421
|
+
url?: string;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
interface PrCreateDuplicateCheck {
|
|
425
|
+
base: string;
|
|
426
|
+
head: string;
|
|
427
|
+
issue?: GhIssueViewData;
|
|
428
|
+
linkedPr?: GhPrListData;
|
|
429
|
+
pr?: GhPrListData;
|
|
430
|
+
}
|
|
410
431
|
|
|
411
432
|
interface GhPrFile {
|
|
412
433
|
path?: string;
|
|
@@ -659,6 +680,185 @@ function resolveSearchLimit(value: number | undefined): number {
|
|
|
659
680
|
|
|
660
681
|
return Math.min(Math.floor(value), SEARCH_LIMIT_MAX);
|
|
661
682
|
}
|
|
683
|
+
async function resolvePrCreateBase(
|
|
684
|
+
cwd: string,
|
|
685
|
+
explicitBase: string | undefined,
|
|
686
|
+
repo: string | undefined,
|
|
687
|
+
signal?: AbortSignal,
|
|
688
|
+
): Promise<string | undefined> {
|
|
689
|
+
if (explicitBase) return explicitBase;
|
|
690
|
+
try {
|
|
691
|
+
for (const key of PR_CREATE_BASE_CONFIG_KEYS) {
|
|
692
|
+
const configured = normalizeOptionalString(await git.config.get(cwd, key, signal));
|
|
693
|
+
if (configured) return configured;
|
|
694
|
+
}
|
|
695
|
+
} catch {
|
|
696
|
+
// Repository config is optional for pr_create; prefer GitHub metadata when
|
|
697
|
+
// local git metadata is unavailable.
|
|
698
|
+
}
|
|
699
|
+
try {
|
|
700
|
+
const resolvedRepo = repo ?? (await resolveDefaultRepoMemoized(cwd, signal));
|
|
701
|
+
const repoView = await git.github.json<GhRepoViewData>(
|
|
702
|
+
cwd,
|
|
703
|
+
["repo", "view", resolvedRepo, "--json", "defaultBranchRef"],
|
|
704
|
+
signal,
|
|
705
|
+
{ repoProvided: true },
|
|
706
|
+
);
|
|
707
|
+
const defaultBranch = normalizeOptionalString(repoView.defaultBranchRef?.name);
|
|
708
|
+
if (defaultBranch) return defaultBranch;
|
|
709
|
+
} catch {
|
|
710
|
+
// Fall back to local git metadata below so pr_create can still work when gh
|
|
711
|
+
// cannot resolve repository metadata in otherwise-valid checkouts.
|
|
712
|
+
}
|
|
713
|
+
return (await git.branch.default(cwd, signal)) ?? undefined;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
function normalizePrHead(value: string): string {
|
|
717
|
+
const separator = value.lastIndexOf(":");
|
|
718
|
+
return separator >= 0 ? value.slice(separator + 1) : value;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
function extractClosingIssueReferences(body: string | undefined, repo: string | undefined): number[] {
|
|
722
|
+
if (!body) return [];
|
|
723
|
+
const issueNumbers: number[] = [];
|
|
724
|
+
ISSUE_CLOSING_REFERENCE_PATTERN.lastIndex = 0;
|
|
725
|
+
let match = ISSUE_CLOSING_REFERENCE_PATTERN.exec(body);
|
|
726
|
+
while (match !== null) {
|
|
727
|
+
const issueRepo = normalizeOptionalString(match[1]);
|
|
728
|
+
if (!issueRepo || !repo || issueRepo.toLowerCase() === repo.toLowerCase()) {
|
|
729
|
+
const issueNumber = Number(match[2]);
|
|
730
|
+
if (Number.isInteger(issueNumber) && issueNumber > 0) issueNumbers.push(issueNumber);
|
|
731
|
+
}
|
|
732
|
+
match = ISSUE_CLOSING_REFERENCE_PATTERN.exec(body);
|
|
733
|
+
}
|
|
734
|
+
return issueNumbers;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
async function resolvePrCreateHead(
|
|
738
|
+
cwd: string,
|
|
739
|
+
explicitHead: string | undefined,
|
|
740
|
+
signal?: AbortSignal,
|
|
741
|
+
): Promise<string | undefined> {
|
|
742
|
+
if (explicitHead) return explicitHead;
|
|
743
|
+
try {
|
|
744
|
+
return (await git.branch.current(cwd, signal)) ?? undefined;
|
|
745
|
+
} catch {
|
|
746
|
+
return undefined;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
async function fetchPrCreateDuplicateCheck(
|
|
751
|
+
cwd: string,
|
|
752
|
+
repo: string | undefined,
|
|
753
|
+
base: string | undefined,
|
|
754
|
+
head: string | undefined,
|
|
755
|
+
body: string | undefined,
|
|
756
|
+
signal: AbortSignal | undefined,
|
|
757
|
+
): Promise<PrCreateDuplicateCheck | undefined> {
|
|
758
|
+
if (!base || !head) return undefined;
|
|
759
|
+
const resolvedRepo = repo ?? (await resolveDefaultRepoMemoized(cwd, signal));
|
|
760
|
+
const normalizedHead = normalizePrHead(head);
|
|
761
|
+
const prs = await git.github.json<GhPrListData[]>(
|
|
762
|
+
cwd,
|
|
763
|
+
[
|
|
764
|
+
"pr",
|
|
765
|
+
"list",
|
|
766
|
+
"--repo",
|
|
767
|
+
resolvedRepo,
|
|
768
|
+
"--head",
|
|
769
|
+
normalizedHead,
|
|
770
|
+
"--base",
|
|
771
|
+
base,
|
|
772
|
+
"--state",
|
|
773
|
+
"all",
|
|
774
|
+
"--json",
|
|
775
|
+
"number,title,state,url,baseRefName,headRefName,isDraft",
|
|
776
|
+
],
|
|
777
|
+
signal,
|
|
778
|
+
{ repoProvided: true },
|
|
779
|
+
);
|
|
780
|
+
const existingPr = prs.find(pr => pr.headRefName === normalizedHead && pr.baseRefName === base) ?? prs[0];
|
|
781
|
+
const issueNumbers = existingPr ? [] : extractClosingIssueReferences(body, resolvedRepo);
|
|
782
|
+
let issue: GhIssueViewData | undefined;
|
|
783
|
+
let linkedPr: GhPrListData | undefined;
|
|
784
|
+
for (const issueNumber of issueNumbers) {
|
|
785
|
+
const candidateIssue = await git.github.json<GhIssueViewData>(
|
|
786
|
+
cwd,
|
|
787
|
+
[
|
|
788
|
+
"issue",
|
|
789
|
+
"view",
|
|
790
|
+
String(issueNumber),
|
|
791
|
+
"--repo",
|
|
792
|
+
resolvedRepo,
|
|
793
|
+
"--json",
|
|
794
|
+
GH_ISSUE_FIELDS_NO_COMMENTS.join(","),
|
|
795
|
+
],
|
|
796
|
+
signal,
|
|
797
|
+
{ repoProvided: true },
|
|
798
|
+
);
|
|
799
|
+
issue = candidateIssue;
|
|
800
|
+
if (candidateIssue.state && candidateIssue.state.toUpperCase() !== "OPEN") break;
|
|
801
|
+
const linkedPrs = await git.github.json<GhPrListData[]>(
|
|
802
|
+
cwd,
|
|
803
|
+
[
|
|
804
|
+
"pr",
|
|
805
|
+
"list",
|
|
806
|
+
"--repo",
|
|
807
|
+
resolvedRepo,
|
|
808
|
+
"--search",
|
|
809
|
+
`${issueNumber} linked:issue`,
|
|
810
|
+
"--state",
|
|
811
|
+
"open",
|
|
812
|
+
"--json",
|
|
813
|
+
"number,title,state,url,baseRefName,headRefName,isDraft",
|
|
814
|
+
],
|
|
815
|
+
signal,
|
|
816
|
+
{ repoProvided: true },
|
|
817
|
+
);
|
|
818
|
+
linkedPr = linkedPrs.find(pr => pr.headRefName !== normalizedHead) ?? linkedPrs[0];
|
|
819
|
+
if (linkedPr) break;
|
|
820
|
+
}
|
|
821
|
+
return { base, head: normalizedHead, issue, linkedPr, pr: existingPr };
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
function formatPrCreateExistingResult(check: PrCreateDuplicateCheck): string | undefined {
|
|
825
|
+
if (check.issue?.state && check.issue.state.toUpperCase() !== "OPEN") {
|
|
826
|
+
const lines = [
|
|
827
|
+
"# Pull Request Not Created",
|
|
828
|
+
"",
|
|
829
|
+
`Issue #${check.issue.number ?? ""} is ${check.issue.state.toLowerCase()}.`,
|
|
830
|
+
];
|
|
831
|
+
pushLine(lines, "Issue", check.issue.url);
|
|
832
|
+
if (check.pr) pushLine(lines, "Existing PR", check.pr.url);
|
|
833
|
+
pushLine(lines, "Base", check.base);
|
|
834
|
+
pushLine(lines, "Head", check.head);
|
|
835
|
+
return lines.join("\n").trim();
|
|
836
|
+
}
|
|
837
|
+
if (check.linkedPr) {
|
|
838
|
+
const number = check.linkedPr.number !== undefined ? ` #${check.linkedPr.number}` : "";
|
|
839
|
+
const title = check.linkedPr.title ? `: ${check.linkedPr.title}` : "";
|
|
840
|
+
const lines = [`# Pull Request Already Linked${number}${title}`, ""];
|
|
841
|
+
pushLine(lines, "URL", check.linkedPr.url);
|
|
842
|
+
pushLine(lines, "Issue", check.issue?.url);
|
|
843
|
+
pushLine(lines, "State", check.linkedPr.state);
|
|
844
|
+
pushLine(lines, "Draft", check.linkedPr.isDraft);
|
|
845
|
+
pushLine(lines, "Base", check.linkedPr.baseRefName ?? check.base);
|
|
846
|
+
pushLine(lines, "Head", check.linkedPr.headRefName ?? check.head);
|
|
847
|
+
return lines.join("\n").trim();
|
|
848
|
+
}
|
|
849
|
+
if (check.pr) {
|
|
850
|
+
const number = check.pr.number !== undefined ? ` #${check.pr.number}` : "";
|
|
851
|
+
const title = check.pr.title ? `: ${check.pr.title}` : "";
|
|
852
|
+
const lines = [`# Pull Request Already Exists${number}${title}`, ""];
|
|
853
|
+
pushLine(lines, "URL", check.pr.url);
|
|
854
|
+
pushLine(lines, "State", check.pr.state);
|
|
855
|
+
pushLine(lines, "Draft", check.pr.isDraft);
|
|
856
|
+
pushLine(lines, "Base", check.pr.baseRefName ?? check.base);
|
|
857
|
+
pushLine(lines, "Head", check.pr.headRefName ?? check.head);
|
|
858
|
+
return lines.join("\n").trim();
|
|
859
|
+
}
|
|
860
|
+
return undefined;
|
|
861
|
+
}
|
|
662
862
|
|
|
663
863
|
function resolveTailLimit(value: number | undefined): number {
|
|
664
864
|
if (value === undefined) {
|
|
@@ -3117,8 +3317,8 @@ async function executePrCreate(
|
|
|
3117
3317
|
const repo = normalizeOptionalString(params.repo);
|
|
3118
3318
|
const title = normalizeOptionalString(params.title);
|
|
3119
3319
|
const body = params.body;
|
|
3120
|
-
const
|
|
3121
|
-
const
|
|
3320
|
+
const requestedBase = normalizeOptionalString(params.base);
|
|
3321
|
+
const requestedHead = normalizeOptionalString(params.head);
|
|
3122
3322
|
const draft = params.draft ?? false;
|
|
3123
3323
|
const fill = params.fill ?? false;
|
|
3124
3324
|
const reviewers = normalizePrIdentifierList(params.reviewer);
|
|
@@ -3131,6 +3331,16 @@ async function executePrCreate(
|
|
|
3131
3331
|
if (fill && (title || body !== undefined)) {
|
|
3132
3332
|
throw new ToolError("fill is mutually exclusive with title and body");
|
|
3133
3333
|
}
|
|
3334
|
+
const base = await resolvePrCreateBase(session.cwd, requestedBase, repo, signal);
|
|
3335
|
+
const head = await resolvePrCreateHead(session.cwd, requestedHead, signal);
|
|
3336
|
+
const duplicateCheck = await fetchPrCreateDuplicateCheck(session.cwd, repo, base, head, body, signal);
|
|
3337
|
+
const existingText = duplicateCheck ? formatPrCreateExistingResult(duplicateCheck) : undefined;
|
|
3338
|
+
if (existingText) {
|
|
3339
|
+
return buildTextResult(
|
|
3340
|
+
existingText,
|
|
3341
|
+
duplicateCheck?.pr?.url ?? duplicateCheck?.linkedPr?.url ?? duplicateCheck?.issue?.url,
|
|
3342
|
+
);
|
|
3343
|
+
}
|
|
3134
3344
|
|
|
3135
3345
|
const args = ["pr", "create"];
|
|
3136
3346
|
appendRepoFlag(args, repo);
|
package/src/tools/index.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentTelemetryConfig, AgentTool } from "@gajae-code/agent-core";
|
|
2
|
-
import type { ToolChoice } from "@gajae-code/ai";
|
|
2
|
+
import type { Model, ToolChoice } from "@gajae-code/ai";
|
|
3
3
|
import { $env, $flag, logger } from "@gajae-code/utils";
|
|
4
4
|
import type { PromptTemplate } from "../config/prompt-templates";
|
|
5
5
|
import type { Settings } from "../config/settings";
|
|
@@ -7,15 +7,17 @@ import { EditTool } from "../edit";
|
|
|
7
7
|
import { checkPythonKernelAvailability } from "../eval/py/kernel";
|
|
8
8
|
import type { Skill } from "../extensibility/skills";
|
|
9
9
|
import type { GoalModeState, GoalRuntime } from "../goals";
|
|
10
|
-
import {
|
|
10
|
+
import { GoalTool } from "../goals/tools/goal-tool";
|
|
11
11
|
import type { HindsightSessionState } from "../hindsight/state";
|
|
12
12
|
import { LspTool } from "../lsp";
|
|
13
13
|
import type { PlanModeState } from "../plan-mode/state";
|
|
14
14
|
import type { AgentRegistry } from "../registry/agent-registry";
|
|
15
|
+
import type { ForkContextSeed, ForkContextSeedOptions } from "../session/agent-session";
|
|
15
16
|
import type { ArtifactManager } from "../session/artifacts";
|
|
16
17
|
import type { ClientBridge } from "../session/client-bridge";
|
|
17
18
|
import type { CustomMessage } from "../session/messages";
|
|
18
19
|
import type { ToolChoiceQueue } from "../session/tool-choice-queue";
|
|
20
|
+
import type { SkillActiveEntry } from "../skill-state/active-state";
|
|
19
21
|
import { TaskTool } from "../task";
|
|
20
22
|
import type { AgentOutputManager } from "../task/output-manager";
|
|
21
23
|
import type { DiscoverableTool, DiscoverableToolSearchIndex } from "../tool-discovery/tool-index";
|
|
@@ -47,6 +49,7 @@ import { ResolveTool } from "./resolve";
|
|
|
47
49
|
import { reportFindingTool } from "./review";
|
|
48
50
|
import { SearchTool } from "./search";
|
|
49
51
|
import { SearchToolBm25Tool } from "./search-tool-bm25";
|
|
52
|
+
import { SkillTool } from "./skill";
|
|
50
53
|
import { loadSshTool } from "./ssh";
|
|
51
54
|
import { SubagentTool } from "./subagent";
|
|
52
55
|
import { type TodoPhase, TodoWriteTool } from "./todo-write";
|
|
@@ -84,6 +87,7 @@ export * from "./resolve";
|
|
|
84
87
|
export * from "./review";
|
|
85
88
|
export * from "./search";
|
|
86
89
|
export * from "./search-tool-bm25";
|
|
90
|
+
export * from "./skill";
|
|
87
91
|
export * from "./ssh";
|
|
88
92
|
export * from "./subagent";
|
|
89
93
|
export * from "./todo-write";
|
|
@@ -122,6 +126,12 @@ export interface ToolSession {
|
|
|
122
126
|
workspaceTree?: WorkspaceTree;
|
|
123
127
|
/** Pre-loaded skills */
|
|
124
128
|
skills?: Skill[];
|
|
129
|
+
/** Currently executing skill prompt, when this tool session is inside one. */
|
|
130
|
+
getActiveSkillState?: () => Pick<SkillActiveEntry, "skill" | "session_id"> | undefined;
|
|
131
|
+
/** Get the active skill prompt's current phase so the skill tool can apply
|
|
132
|
+
* its terminal-phase chain guard. Returns the raw phase string or undefined
|
|
133
|
+
* when no active skill (or accessor) is available. */
|
|
134
|
+
getActiveSkillPhase?: () => string | undefined;
|
|
125
135
|
/** Pre-loaded prompt templates */
|
|
126
136
|
promptTemplates?: PromptTemplate[];
|
|
127
137
|
/** Whether LSP integrations are enabled */
|
|
@@ -164,6 +174,8 @@ export interface ToolSession {
|
|
|
164
174
|
getSessionSpawns: () => string | null;
|
|
165
175
|
/** Get resolved model string if explicitly set for this session */
|
|
166
176
|
getModelString?: () => string | undefined;
|
|
177
|
+
/** Current model, when selected. */
|
|
178
|
+
model?: Model;
|
|
167
179
|
/** Get the current session model string, regardless of how it was chosen */
|
|
168
180
|
getActiveModelString?: () => string | undefined;
|
|
169
181
|
/** Auth storage for passing to subagents (avoids re-discovery) */
|
|
@@ -246,9 +258,17 @@ export interface ToolSession {
|
|
|
246
258
|
|
|
247
259
|
/** Queue a hidden message to be injected at the next agent turn. */
|
|
248
260
|
queueDeferredMessage?(message: CustomMessage): void;
|
|
261
|
+
/** Dispatch a custom message through the active session. Used by the `skill`
|
|
262
|
+
* tool to dispatch another skill prompt same-turn after recording a handoff. */
|
|
263
|
+
sendCustomMessage?(
|
|
264
|
+
message: Pick<CustomMessage, "customType" | "content" | "display" | "details" | "attribution">,
|
|
265
|
+
options?: { triggerTurn?: boolean; deliverAs?: "steer" | "followUp" | "nextTurn" },
|
|
266
|
+
): Promise<void>;
|
|
249
267
|
/** Get the active OpenTelemetry config so subagent dispatch can forward
|
|
250
268
|
* the parent's tracer/hooks with the subagent's own identity stamped. */
|
|
251
269
|
getTelemetry?: () => AgentTelemetryConfig | undefined;
|
|
270
|
+
/** Build a sanitized fork-context seed for task subagents. */
|
|
271
|
+
buildForkContextSeed?: (options: ForkContextSeedOptions) => Promise<ForkContextSeed>;
|
|
252
272
|
}
|
|
253
273
|
|
|
254
274
|
export type ToolFactory = (session: ToolSession) => Tool | null | Promise<Tool | null>;
|
|
@@ -308,13 +328,11 @@ export const BUILTIN_TOOLS: Record<string, ToolFactory> = {
|
|
|
308
328
|
retain: HindsightRetainTool.createIf,
|
|
309
329
|
recall: HindsightRecallTool.createIf,
|
|
310
330
|
reflect: HindsightReflectTool.createIf,
|
|
331
|
+
skill: SkillTool.createIf,
|
|
311
332
|
goal: s => new GoalTool(s),
|
|
312
|
-
get_goal: GetGoalTool.createIf,
|
|
313
|
-
create_goal: CreateGoalTool.createIf,
|
|
314
|
-
update_goal: UpdateGoalTool.createIf,
|
|
315
333
|
};
|
|
316
334
|
|
|
317
|
-
const GOAL_MODE_TOOL_NAMES = [
|
|
335
|
+
const GOAL_MODE_TOOL_NAMES = [] as const;
|
|
318
336
|
|
|
319
337
|
export const HIDDEN_TOOLS: Record<string, ToolFactory> = {
|
|
320
338
|
yield: s => new YieldTool(s),
|
|
@@ -467,6 +485,7 @@ export async function createTools(session: ToolSession, toolNames?: string[]): P
|
|
|
467
485
|
// search_tool_bm25 is allowed when either legacy mcp.discoveryMode or new tools.discoveryMode is active.
|
|
468
486
|
if (name === "search_tool_bm25") return discoveryActive;
|
|
469
487
|
if (name === "calc") return session.settings.get("calc.enabled");
|
|
488
|
+
if (name === "skill") return session.settings.get("skill.enabled");
|
|
470
489
|
if (name === "browser") return session.settings.get("browser.enabled");
|
|
471
490
|
if (name === "checkpoint" || name === "rewind") return session.settings.get("checkpoint.enabled");
|
|
472
491
|
if (name === "irc") {
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Tool — agent-initiated skill chaining.
|
|
3
|
+
*
|
|
4
|
+
* Lets the agent hand off to another available skill in the current turn. The
|
|
5
|
+
* callee's SKILL.md is dispatched through the same custom-message path used by
|
|
6
|
+
* `/skill:<name>` typing, as a user-attribution message delivered same-turn
|
|
7
|
+
* (without `deliverAs: "nextTurn"`). Before dispatch, the tool calls
|
|
8
|
+
* `gjc state <caller> handoff --to <callee>` in-process via the state-runtime
|
|
9
|
+
* function so caller and callee mode-states plus `skill-active-state.json`
|
|
10
|
+
* transition atomically.
|
|
11
|
+
*
|
|
12
|
+
* Chaining is refused unless the caller's `current_phase` is in
|
|
13
|
+
* `{complete, completed, handoff, failed, cancelled, canceled, inactive}`. The
|
|
14
|
+
* agent declares readiness either by writing `current_phase: "handoff"` to its
|
|
15
|
+
* mode-state or by running the handoff verb directly.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { AgentTool, AgentToolResult } from "@gajae-code/agent-core";
|
|
19
|
+
import { prompt, untilAborted } from "@gajae-code/utils";
|
|
20
|
+
import * as z from "zod/v4";
|
|
21
|
+
import { buildSkillPromptMessage } from "../extensibility/skills";
|
|
22
|
+
import { runNativeStateCommand } from "../gjc-runtime/state-runtime";
|
|
23
|
+
import skillDescription from "../prompts/tools/skill.md" with { type: "text" };
|
|
24
|
+
import { SKILL_PROMPT_MESSAGE_TYPE } from "../session/messages";
|
|
25
|
+
import type { ToolSession } from ".";
|
|
26
|
+
import { ToolError } from "./tool-errors";
|
|
27
|
+
|
|
28
|
+
const TERMINAL_PHASES = new Set(["complete", "completed", "handoff", "failed", "cancelled", "canceled", "inactive"]);
|
|
29
|
+
|
|
30
|
+
const skillSchema = z.object({
|
|
31
|
+
name: z.string().describe("skill name as it appears in /skill:<name>"),
|
|
32
|
+
args: z.string().describe("argument string passed to the skill").optional(),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
function normalizeSkillName(name: string | undefined): string {
|
|
36
|
+
return (name ?? "").trim();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
type SkillToolInput = z.infer<typeof skillSchema>;
|
|
40
|
+
|
|
41
|
+
export interface SkillToolDetails {
|
|
42
|
+
name: string;
|
|
43
|
+
path: string;
|
|
44
|
+
args?: string;
|
|
45
|
+
lineCount: number;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export class SkillTool implements AgentTool<typeof skillSchema, SkillToolDetails> {
|
|
49
|
+
readonly name = "skill";
|
|
50
|
+
readonly label = "Skill";
|
|
51
|
+
readonly summary = "Chain into another available skill in the current turn";
|
|
52
|
+
readonly loadMode = "discoverable";
|
|
53
|
+
readonly description: string;
|
|
54
|
+
readonly parameters = skillSchema;
|
|
55
|
+
readonly strict = true;
|
|
56
|
+
|
|
57
|
+
readonly #session: ToolSession;
|
|
58
|
+
|
|
59
|
+
constructor(session: ToolSession) {
|
|
60
|
+
this.#session = session;
|
|
61
|
+
this.description = prompt.render(skillDescription);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
static createIf(session: ToolSession): SkillTool | null {
|
|
65
|
+
// The tool can only chain when the session can deliver the same-turn
|
|
66
|
+
// custom message. Without `sendCustomMessage` (e.g. minimal tool
|
|
67
|
+
// harnesses in tests) there is nothing useful to do.
|
|
68
|
+
if (!session.sendCustomMessage) return null;
|
|
69
|
+
const skills = session.skills ?? [];
|
|
70
|
+
if (skills.length === 0) return null;
|
|
71
|
+
return new SkillTool(session);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async execute(
|
|
75
|
+
_toolCallId: string,
|
|
76
|
+
input: SkillToolInput,
|
|
77
|
+
signal?: AbortSignal,
|
|
78
|
+
): Promise<AgentToolResult<SkillToolDetails>> {
|
|
79
|
+
return untilAborted(signal, async () => {
|
|
80
|
+
const sendCustomMessage = this.#session.sendCustomMessage;
|
|
81
|
+
if (!sendCustomMessage) {
|
|
82
|
+
throw new ToolError("skill tool: session has no custom-message bridge");
|
|
83
|
+
}
|
|
84
|
+
const skills = this.#session.skills ?? [];
|
|
85
|
+
const requestedName = normalizeSkillName(input.name);
|
|
86
|
+
if (!requestedName) {
|
|
87
|
+
throw new ToolError("skill tool: `name` is required");
|
|
88
|
+
}
|
|
89
|
+
const activeState = this.#session.getActiveSkillState?.();
|
|
90
|
+
const activeSkill = normalizeSkillName(activeState?.skill);
|
|
91
|
+
if (activeSkill && requestedName === activeSkill) {
|
|
92
|
+
throw new ToolError(
|
|
93
|
+
`skill tool: refusing to chain into currently active skill "${requestedName}". Follow the active skill instructions instead of invoking it recursively.`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const skill = skills.find(s => s.name === requestedName);
|
|
98
|
+
if (!skill) {
|
|
99
|
+
const available = skills.map(s => s.name).sort();
|
|
100
|
+
const hint = available.length > 0 ? ` Available: ${available.join(", ")}` : "";
|
|
101
|
+
throw new ToolError(`skill tool: unknown skill "${requestedName}".${hint}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Phase guard + atomic handoff. Only runs when transitioning between
|
|
105
|
+
// distinct skills (same-skill recursion was already refused above).
|
|
106
|
+
if (activeSkill) {
|
|
107
|
+
const phase = (this.#session.getActiveSkillPhase?.() ?? "running").trim().toLowerCase();
|
|
108
|
+
if (!TERMINAL_PHASES.has(phase)) {
|
|
109
|
+
throw new ToolError(
|
|
110
|
+
`skill tool: refusing to chain from "${activeSkill}" (phase=${phase}) into "${requestedName}". Finalize the current skill (gjc state ${activeSkill} write --input '{"current_phase":"handoff"}' --json) or run gjc state ${activeSkill} handoff --to ${requestedName} --json directly before chaining.`,
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
const cwd = this.#session.cwd;
|
|
114
|
+
const sessionId = activeState?.session_id?.trim();
|
|
115
|
+
const handoffArgs = ["handoff", "--mode", activeSkill, "--to", requestedName, "--json"];
|
|
116
|
+
if (sessionId) {
|
|
117
|
+
handoffArgs.push("--session-id", sessionId);
|
|
118
|
+
}
|
|
119
|
+
const handoff = await runNativeStateCommand(handoffArgs, cwd);
|
|
120
|
+
if (handoff.status !== 0) {
|
|
121
|
+
throw new ToolError(
|
|
122
|
+
`skill tool: handoff failed (status=${handoff.status}): ${(handoff.stderr ?? "").trim() || "no detail"}`,
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const args = (input.args ?? "").trim();
|
|
128
|
+
const built = await buildSkillPromptMessage(skill, args);
|
|
129
|
+
|
|
130
|
+
await sendCustomMessage(
|
|
131
|
+
{
|
|
132
|
+
customType: SKILL_PROMPT_MESSAGE_TYPE,
|
|
133
|
+
content: built.message,
|
|
134
|
+
display: true,
|
|
135
|
+
details: built.details,
|
|
136
|
+
attribution: "user",
|
|
137
|
+
},
|
|
138
|
+
{ triggerTurn: false },
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
const summary = args ? `Handed off to /skill:${skill.name} ${args}.` : `Handed off to /skill:${skill.name}.`;
|
|
142
|
+
return {
|
|
143
|
+
content: [{ type: "text", text: summary }],
|
|
144
|
+
details: {
|
|
145
|
+
name: skill.name,
|
|
146
|
+
path: skill.filePath,
|
|
147
|
+
args: args || undefined,
|
|
148
|
+
lineCount: built.details.lineCount,
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
package/src/utils/changelog.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isEnoent, logger } from "@gajae-code/utils";
|
|
2
|
+
import CHANGELOG_TEXT from "../../CHANGELOG.md" with { type: "text" };
|
|
2
3
|
|
|
3
4
|
export interface ChangelogEntry {
|
|
4
5
|
major: number;
|
|
@@ -8,58 +9,67 @@ export interface ChangelogEntry {
|
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
|
-
* Parse changelog entries from CHANGELOG.md
|
|
12
|
-
* Scans for ## lines and collects content until next ## or EOF
|
|
12
|
+
* Parse changelog entries from a CHANGELOG.md text body.
|
|
13
|
+
* Scans for ## lines and collects content until next ## or EOF.
|
|
14
|
+
* Pure and synchronous so it can be reused by the embedded display path.
|
|
13
15
|
*/
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const lines = content.split("\n");
|
|
18
|
-
const entries: ChangelogEntry[] = [];
|
|
16
|
+
export function parseChangelogContent(content: string): ChangelogEntry[] {
|
|
17
|
+
const lines = content.split("\n");
|
|
18
|
+
const entries: ChangelogEntry[] = [];
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
let currentLines: string[] = [];
|
|
21
|
+
let currentVersion: { major: number; minor: number; patch: number } | null = null;
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
for (const line of lines) {
|
|
24
|
+
// Check if this is a version header (## [x.y.z] ...)
|
|
25
|
+
if (line.startsWith("## ")) {
|
|
26
|
+
// Save previous entry if exists
|
|
27
|
+
if (currentVersion && currentLines.length > 0) {
|
|
28
|
+
entries.push({
|
|
29
|
+
...currentVersion,
|
|
30
|
+
content: currentLines.join("\n").trim(),
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
} else if (currentVersion) {
|
|
49
|
-
// Collect lines for current version
|
|
50
|
-
currentLines.push(line);
|
|
34
|
+
// Try to parse version from this line
|
|
35
|
+
const versionMatch = line.match(/##\s+\[?(\d+)\.(\d+)\.(\d+)\]?/);
|
|
36
|
+
if (versionMatch) {
|
|
37
|
+
currentVersion = {
|
|
38
|
+
major: Number.parseInt(versionMatch[1], 10),
|
|
39
|
+
minor: Number.parseInt(versionMatch[2], 10),
|
|
40
|
+
patch: Number.parseInt(versionMatch[3], 10),
|
|
41
|
+
};
|
|
42
|
+
currentLines = [line];
|
|
43
|
+
} else {
|
|
44
|
+
// Reset if we can't parse version
|
|
45
|
+
currentVersion = null;
|
|
46
|
+
currentLines = [];
|
|
51
47
|
}
|
|
48
|
+
} else if (currentVersion) {
|
|
49
|
+
// Collect lines for current version
|
|
50
|
+
currentLines.push(line);
|
|
52
51
|
}
|
|
52
|
+
}
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
// Save last entry
|
|
55
|
+
if (currentVersion && currentLines.length > 0) {
|
|
56
|
+
entries.push({
|
|
57
|
+
...currentVersion,
|
|
58
|
+
content: currentLines.join("\n").trim(),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return entries;
|
|
63
|
+
}
|
|
61
64
|
|
|
62
|
-
|
|
65
|
+
/**
|
|
66
|
+
* Parse changelog entries from a CHANGELOG.md file on disk.
|
|
67
|
+
* Returns [] on ENOENT; logs and returns [] on other read/parse errors.
|
|
68
|
+
*/
|
|
69
|
+
export async function parseChangelog(changelogPath: string): Promise<ChangelogEntry[]> {
|
|
70
|
+
try {
|
|
71
|
+
const content = await Bun.file(changelogPath).text();
|
|
72
|
+
return parseChangelogContent(content);
|
|
63
73
|
} catch (error) {
|
|
64
74
|
if (isEnoent(error)) {
|
|
65
75
|
return [];
|
|
@@ -69,6 +79,19 @@ export async function parseChangelog(changelogPath: string): Promise<ChangelogEn
|
|
|
69
79
|
}
|
|
70
80
|
}
|
|
71
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Return changelog entries from the CHANGELOG.md that shipped with this binary.
|
|
84
|
+
*
|
|
85
|
+
* The text is embedded at build time via `with { type: "text" }`, so the
|
|
86
|
+
* displayed changelog is deterministic across compiled binaries, source-tree
|
|
87
|
+
* dev runs, and `GJC_PACKAGE_DIR` / `PI_PACKAGE_DIR` overrides (which scope to
|
|
88
|
+
* optional package assets like docs/examples and do not influence the
|
|
89
|
+
* binary-identity changelog).
|
|
90
|
+
*/
|
|
91
|
+
export function getDisplayChangelogEntries(): ChangelogEntry[] {
|
|
92
|
+
return parseChangelogContent(CHANGELOG_TEXT);
|
|
93
|
+
}
|
|
94
|
+
|
|
72
95
|
/**
|
|
73
96
|
* Compare versions. Returns: -1 if v1 < v2, 0 if v1 === v2, 1 if v1 > v2
|
|
74
97
|
*/
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { type WorkflowHudSummary } from "../skill-state/active-state";
|
|
2
|
-
export declare const WORKFLOW_HUD_PROTOCOL = "workflow-hud-summary-v1";
|
|
3
|
-
export interface GjcRuntimeBridgeResult {
|
|
4
|
-
status: number;
|
|
5
|
-
error?: string;
|
|
6
|
-
}
|
|
7
|
-
export interface WorkflowHudBridgePayload {
|
|
8
|
-
version: 1;
|
|
9
|
-
skill: string;
|
|
10
|
-
phase?: string;
|
|
11
|
-
active?: boolean;
|
|
12
|
-
session_id?: string;
|
|
13
|
-
thread_id?: string;
|
|
14
|
-
turn_id?: string;
|
|
15
|
-
hud: WorkflowHudSummary;
|
|
16
|
-
}
|
|
17
|
-
export interface GjcRuntimeHudBridgeResult extends GjcRuntimeBridgeResult {
|
|
18
|
-
hudPayload?: WorkflowHudBridgePayload;
|
|
19
|
-
}
|
|
20
|
-
export interface GjcRuntimeHudBridgeOptions {
|
|
21
|
-
cwd?: string;
|
|
22
|
-
env?: NodeJS.ProcessEnv;
|
|
23
|
-
sidecarSkill: string;
|
|
24
|
-
onHudPayload?: (payload: WorkflowHudBridgePayload) => Promise<void> | void;
|
|
25
|
-
pollIntervalMs?: number;
|
|
26
|
-
}
|
|
27
|
-
export declare function normalizeWorkflowHudBridgePayload(raw: unknown, expectedSkill: string): WorkflowHudBridgePayload | null;
|
|
28
|
-
export declare function runGjcRuntimeBridge(endpoint: string, args: string[], env?: NodeJS.ProcessEnv): GjcRuntimeBridgeResult;
|
|
29
|
-
export declare function runGjcRuntimeBridgeWithHudSidecar(endpoint: string, args: string[], options: GjcRuntimeHudBridgeOptions): Promise<GjcRuntimeHudBridgeResult>;
|
|
30
|
-
export declare function runBridgedRuntimeEndpoint(endpoint: string, args: string[]): Promise<void>;
|