@joynt/foundry 0.0.0-stage → 0.1.50
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/backends/command.d.ts +37 -0
- package/dist/backends/command.d.ts.map +1 -0
- package/dist/backends/command.js +79 -0
- package/dist/backends/command.js.map +1 -0
- package/dist/backends/index.d.ts +9 -0
- package/dist/backends/index.d.ts.map +1 -0
- package/dist/backends/index.js +37 -0
- package/dist/backends/index.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +191 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/action.d.ts +6 -0
- package/dist/commands/action.d.ts.map +1 -0
- package/dist/commands/action.js +171 -0
- package/dist/commands/action.js.map +1 -0
- package/dist/commands/cancelled.d.ts +5 -0
- package/dist/commands/cancelled.d.ts.map +1 -0
- package/dist/commands/cancelled.js +107 -0
- package/dist/commands/cancelled.js.map +1 -0
- package/dist/commands/init.d.ts +5 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +323 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/preview.d.ts +4 -0
- package/dist/commands/preview.d.ts.map +1 -0
- package/dist/commands/preview.js +108 -0
- package/dist/commands/preview.js.map +1 -0
- package/dist/commands/release.d.ts +2 -0
- package/dist/commands/release.d.ts.map +1 -0
- package/dist/commands/release.js +89 -0
- package/dist/commands/release.js.map +1 -0
- package/dist/commands/report.d.ts +14 -0
- package/dist/commands/report.d.ts.map +1 -0
- package/dist/commands/report.js +91 -0
- package/dist/commands/report.js.map +1 -0
- package/dist/commands/reset.d.ts +4 -0
- package/dist/commands/reset.d.ts.map +1 -0
- package/dist/commands/reset.js +155 -0
- package/dist/commands/reset.js.map +1 -0
- package/dist/commands/review.d.ts +2 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +73 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/setup-bot.d.ts +31 -0
- package/dist/commands/setup-bot.d.ts.map +1 -0
- package/dist/commands/setup-bot.js +429 -0
- package/dist/commands/setup-bot.js.map +1 -0
- package/dist/commands/sync.d.ts +2 -0
- package/dist/commands/sync.d.ts.map +1 -0
- package/dist/commands/sync.js +77 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +147 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/agent-output.d.ts +49 -0
- package/dist/lib/agent-output.d.ts.map +1 -0
- package/dist/lib/agent-output.js +256 -0
- package/dist/lib/agent-output.js.map +1 -0
- package/dist/lib/agent-report.d.ts +107 -0
- package/dist/lib/agent-report.d.ts.map +1 -0
- package/dist/lib/agent-report.js +233 -0
- package/dist/lib/agent-report.js.map +1 -0
- package/dist/lib/authorize.d.ts +3 -0
- package/dist/lib/authorize.d.ts.map +1 -0
- package/dist/lib/authorize.js +67 -0
- package/dist/lib/authorize.js.map +1 -0
- package/dist/lib/branches.d.ts +22 -0
- package/dist/lib/branches.d.ts.map +1 -0
- package/dist/lib/branches.js +82 -0
- package/dist/lib/branches.js.map +1 -0
- package/dist/lib/claim.d.ts +22 -0
- package/dist/lib/claim.d.ts.map +1 -0
- package/dist/lib/claim.js +129 -0
- package/dist/lib/claim.js.map +1 -0
- package/dist/lib/completion.d.ts +5 -0
- package/dist/lib/completion.d.ts.map +1 -0
- package/dist/lib/completion.js +63 -0
- package/dist/lib/completion.js.map +1 -0
- package/dist/lib/deployments.d.ts +21 -0
- package/dist/lib/deployments.d.ts.map +1 -0
- package/dist/lib/deployments.js +104 -0
- package/dist/lib/deployments.js.map +1 -0
- package/dist/lib/event-handler.d.ts +74 -0
- package/dist/lib/event-handler.d.ts.map +1 -0
- package/dist/lib/event-handler.js +1002 -0
- package/dist/lib/event-handler.js.map +1 -0
- package/dist/lib/events.d.ts +72 -0
- package/dist/lib/events.d.ts.map +1 -0
- package/dist/lib/events.js +3 -0
- package/dist/lib/events.js.map +1 -0
- package/dist/lib/gh-cli-client.d.ts +46 -0
- package/dist/lib/gh-cli-client.d.ts.map +1 -0
- package/dist/lib/gh-cli-client.js +260 -0
- package/dist/lib/gh-cli-client.js.map +1 -0
- package/dist/lib/git.d.ts +42 -0
- package/dist/lib/git.d.ts.map +1 -0
- package/dist/lib/git.js +247 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/github-client.d.ts +98 -0
- package/dist/lib/github-client.d.ts.map +1 -0
- package/dist/lib/github-client.js +3 -0
- package/dist/lib/github-client.js.map +1 -0
- package/dist/lib/github.d.ts +82 -0
- package/dist/lib/github.d.ts.map +1 -0
- package/dist/lib/github.js +202 -0
- package/dist/lib/github.js.map +1 -0
- package/dist/lib/issue-file.d.ts +15 -0
- package/dist/lib/issue-file.d.ts.map +1 -0
- package/dist/lib/issue-file.js +84 -0
- package/dist/lib/issue-file.js.map +1 -0
- package/dist/lib/labels.d.ts +14 -0
- package/dist/lib/labels.d.ts.map +1 -0
- package/dist/lib/labels.js +70 -0
- package/dist/lib/labels.js.map +1 -0
- package/dist/lib/log.d.ts +11 -0
- package/dist/lib/log.d.ts.map +1 -0
- package/dist/lib/log.js +53 -0
- package/dist/lib/log.js.map +1 -0
- package/dist/lib/octokit-client.d.ts +112 -0
- package/dist/lib/octokit-client.d.ts.map +1 -0
- package/dist/lib/octokit-client.js +507 -0
- package/dist/lib/octokit-client.js.map +1 -0
- package/dist/lib/preview-verify.d.ts +48 -0
- package/dist/lib/preview-verify.d.ts.map +1 -0
- package/dist/lib/preview-verify.js +148 -0
- package/dist/lib/preview-verify.js.map +1 -0
- package/dist/lib/preview.d.ts +33 -0
- package/dist/lib/preview.d.ts.map +1 -0
- package/dist/lib/preview.js +308 -0
- package/dist/lib/preview.js.map +1 -0
- package/dist/lib/reconcile.d.ts +14 -0
- package/dist/lib/reconcile.d.ts.map +1 -0
- package/dist/lib/reconcile.js +114 -0
- package/dist/lib/reconcile.js.map +1 -0
- package/dist/lib/review.d.ts +38 -0
- package/dist/lib/review.d.ts.map +1 -0
- package/dist/lib/review.js +284 -0
- package/dist/lib/review.js.map +1 -0
- package/dist/lib/stale-prs.d.ts +31 -0
- package/dist/lib/stale-prs.d.ts.map +1 -0
- package/dist/lib/stale-prs.js +161 -0
- package/dist/lib/stale-prs.js.map +1 -0
- package/dist/lib/state-store.d.ts +23 -0
- package/dist/lib/state-store.d.ts.map +1 -0
- package/dist/lib/state-store.js +3 -0
- package/dist/lib/state-store.js.map +1 -0
- package/dist/lib/state.d.ts +23 -0
- package/dist/lib/state.d.ts.map +1 -0
- package/dist/lib/state.js +57 -0
- package/dist/lib/state.js.map +1 -0
- package/dist/lib/status-comment.d.ts +14 -0
- package/dist/lib/status-comment.d.ts.map +1 -0
- package/dist/lib/status-comment.js +195 -0
- package/dist/lib/status-comment.js.map +1 -0
- package/dist/lib/stores/file-store.d.ts +22 -0
- package/dist/lib/stores/file-store.d.ts.map +1 -0
- package/dist/lib/stores/file-store.js +172 -0
- package/dist/lib/stores/file-store.js.map +1 -0
- package/dist/lib/stores/index.d.ts +13 -0
- package/dist/lib/stores/index.d.ts.map +1 -0
- package/dist/lib/stores/index.js +20 -0
- package/dist/lib/stores/index.js.map +1 -0
- package/dist/lib/task-recovery.d.ts +22 -0
- package/dist/lib/task-recovery.d.ts.map +1 -0
- package/dist/lib/task-recovery.js +172 -0
- package/dist/lib/task-recovery.js.map +1 -0
- package/dist/lib/templates.d.ts +8 -0
- package/dist/lib/templates.d.ts.map +1 -0
- package/dist/lib/templates.js +58 -0
- package/dist/lib/templates.js.map +1 -0
- package/dist/lib/thread.d.ts +13 -0
- package/dist/lib/thread.d.ts.map +1 -0
- package/dist/lib/thread.js +75 -0
- package/dist/lib/thread.js.map +1 -0
- package/dist/lib/verify.d.ts +31 -0
- package/dist/lib/verify.d.ts.map +1 -0
- package/dist/lib/verify.js +90 -0
- package/dist/lib/verify.js.map +1 -0
- package/dist/lib/version.d.ts +9 -0
- package/dist/lib/version.d.ts.map +1 -0
- package/dist/lib/version.js +134 -0
- package/dist/lib/version.js.map +1 -0
- package/dist/lib/webhook.d.ts +39 -0
- package/dist/lib/webhook.d.ts.map +1 -0
- package/dist/lib/webhook.js +248 -0
- package/dist/lib/webhook.js.map +1 -0
- package/dist/lib/worker.d.ts +42 -0
- package/dist/lib/worker.d.ts.map +1 -0
- package/dist/lib/worker.js +9 -0
- package/dist/lib/worker.js.map +1 -0
- package/dist/lib/workers/index.d.ts +11 -0
- package/dist/lib/workers/index.d.ts.map +1 -0
- package/dist/lib/workers/index.js +18 -0
- package/dist/lib/workers/index.js.map +1 -0
- package/dist/lib/workers/subprocess.d.ts +8 -0
- package/dist/lib/workers/subprocess.d.ts.map +1 -0
- package/dist/lib/workers/subprocess.js +105 -0
- package/dist/lib/workers/subprocess.js.map +1 -0
- package/dist/lib/worktree.d.ts +21 -0
- package/dist/lib/worktree.d.ts.map +1 -0
- package/dist/lib/worktree.js +113 -0
- package/dist/lib/worktree.js.map +1 -0
- package/dist/types.d.ts +201 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +44 -4
- package/templates/foundry.yml +121 -0
- package/templates/vercel-preview-url.sh +61 -0
- package/README.md +0 -3
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub event mapping — converts a GitHub event payload (as delivered to a
|
|
3
|
+
* GitHub Actions job in $GITHUB_EVENT_PATH) into FoundryEvent instances.
|
|
4
|
+
*
|
|
5
|
+
* What starts work is deliberately small:
|
|
6
|
+
* - an `@foundry go|restart|stop` comment on an issue (not on a PR),
|
|
7
|
+
* - a review requesting changes or approving,
|
|
8
|
+
* - a merge,
|
|
9
|
+
* - a `workflow_dispatch` carrying one of the three commands.
|
|
10
|
+
* Labels never start anything and plain comments never start anything.
|
|
11
|
+
*/
|
|
12
|
+
import type { FoundryEvent, FoundryCommand } from './events.js';
|
|
13
|
+
import type { FoundryConfig } from '../types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Map a GitHub webhook event + payload into zero or more FoundryEvents.
|
|
16
|
+
*
|
|
17
|
+
* Returns an empty array when the event is irrelevant to Foundry.
|
|
18
|
+
*/
|
|
19
|
+
export declare function webhookToEvents(eventName: string, payload: Record<string, any>, config: FoundryConfig): FoundryEvent[];
|
|
20
|
+
export interface ParsedFoundryCommand {
|
|
21
|
+
name: FoundryCommand;
|
|
22
|
+
message?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Recognise a command at the very start of a comment. `go` takes a message
|
|
26
|
+
* (same line or following lines); `restart` and `stop` are the first line on
|
|
27
|
+
* their own. A mention anywhere else in a comment is just text.
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseFoundryCommand(body: string, config: FoundryConfig): ParsedFoundryCommand | null;
|
|
30
|
+
/**
|
|
31
|
+
* The part of a comment that is not the command: the message after `go`, or
|
|
32
|
+
* whatever followed a `restart`/`stop` line. Null when the comment is not a
|
|
33
|
+
* command at all. Used to keep command comments in the agent's thread
|
|
34
|
+
* without the command text itself.
|
|
35
|
+
*/
|
|
36
|
+
export declare function commandRemainder(body: string, config: FoundryConfig): string | null;
|
|
37
|
+
/** Comments by GitHub Apps, Actions, and Foundry itself are never commands or context. */
|
|
38
|
+
export declare function isBotLogin(login: string): boolean;
|
|
39
|
+
//# sourceMappingURL=webhook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/lib/webhook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAKjD;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC5B,MAAM,EAAE,aAAa,GACpB,YAAY,EAAE,CAoBhB;AAID,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAMD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,oBAAoB,GAAG,IAAI,CAYpG;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAMnF;AAED,0FAA0F;AAC1F,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEjD"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.webhookToEvents = webhookToEvents;
|
|
37
|
+
exports.parseFoundryCommand = parseFoundryCommand;
|
|
38
|
+
exports.commandRemainder = commandRemainder;
|
|
39
|
+
exports.isBotLogin = isBotLogin;
|
|
40
|
+
const state = __importStar(require("./state.js"));
|
|
41
|
+
// ── Event mapping ───────────────────────────────────────────────────────
|
|
42
|
+
/**
|
|
43
|
+
* Map a GitHub webhook event + payload into zero or more FoundryEvents.
|
|
44
|
+
*
|
|
45
|
+
* Returns an empty array when the event is irrelevant to Foundry.
|
|
46
|
+
*/
|
|
47
|
+
function webhookToEvents(eventName, payload, config) {
|
|
48
|
+
const action = payload.action;
|
|
49
|
+
const fullEvent = action ? `${eventName}.${action}` : eventName;
|
|
50
|
+
switch (fullEvent) {
|
|
51
|
+
case 'issue_comment.created':
|
|
52
|
+
return mapIssueComment(payload, config);
|
|
53
|
+
case 'pull_request.opened':
|
|
54
|
+
case 'pull_request.reopened':
|
|
55
|
+
case 'pull_request.synchronize':
|
|
56
|
+
return mapPullRequestPreview(payload, config, 'up');
|
|
57
|
+
case 'pull_request.closed':
|
|
58
|
+
return mapPullRequestClosed(payload, config);
|
|
59
|
+
case 'pull_request_review.submitted':
|
|
60
|
+
return mapPullRequestReview(payload, config);
|
|
61
|
+
case 'workflow_dispatch':
|
|
62
|
+
return mapWorkflowDispatch(payload, config);
|
|
63
|
+
default:
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function escapeRegExp(s) {
|
|
68
|
+
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Recognise a command at the very start of a comment. `go` takes a message
|
|
72
|
+
* (same line or following lines); `restart` and `stop` are the first line on
|
|
73
|
+
* their own. A mention anywhere else in a comment is just text.
|
|
74
|
+
*/
|
|
75
|
+
function parseFoundryCommand(body, config) {
|
|
76
|
+
const t = config.comment_triggers;
|
|
77
|
+
const trimmed = body.trim();
|
|
78
|
+
const firstLine = trimmed.split('\n')[0].trim();
|
|
79
|
+
if (new RegExp('^' + escapeRegExp(t.go) + '(?=\\s|$)').test(trimmed)) {
|
|
80
|
+
const msg = trimmed.slice(t.go.length).trim();
|
|
81
|
+
return { name: 'go', message: msg || undefined };
|
|
82
|
+
}
|
|
83
|
+
if (firstLine === t.restart)
|
|
84
|
+
return { name: 'restart' };
|
|
85
|
+
if (firstLine === t.stop)
|
|
86
|
+
return { name: 'stop' };
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The part of a comment that is not the command: the message after `go`, or
|
|
91
|
+
* whatever followed a `restart`/`stop` line. Null when the comment is not a
|
|
92
|
+
* command at all. Used to keep command comments in the agent's thread
|
|
93
|
+
* without the command text itself.
|
|
94
|
+
*/
|
|
95
|
+
function commandRemainder(body, config) {
|
|
96
|
+
const cmd = parseFoundryCommand(body, config);
|
|
97
|
+
if (!cmd)
|
|
98
|
+
return null;
|
|
99
|
+
if (cmd.name === 'go')
|
|
100
|
+
return cmd.message ?? '';
|
|
101
|
+
const lines = body.trim().split('\n');
|
|
102
|
+
return lines.slice(1).join('\n').trim();
|
|
103
|
+
}
|
|
104
|
+
/** Comments by GitHub Apps, Actions, and Foundry itself are never commands or context. */
|
|
105
|
+
function isBotLogin(login) {
|
|
106
|
+
return login.includes('[bot]') || login === 'github-actions' || login === 'foundry';
|
|
107
|
+
}
|
|
108
|
+
// ── issue_comment.created ───────────────────────────────────────────────
|
|
109
|
+
function mapIssueComment(payload, config) {
|
|
110
|
+
const comment = payload.comment;
|
|
111
|
+
const issue = payload.issue;
|
|
112
|
+
if (!comment || !issue)
|
|
113
|
+
return [];
|
|
114
|
+
// A comment on a pull request arrives as an issue_comment whose number is
|
|
115
|
+
// the PR's. It is not resolved to its issue yet, and must never be mistaken
|
|
116
|
+
// for the issue with the same number.
|
|
117
|
+
if (issue.pull_request)
|
|
118
|
+
return [];
|
|
119
|
+
const author = comment.user?.login ?? '';
|
|
120
|
+
if (isBotLogin(author))
|
|
121
|
+
return [];
|
|
122
|
+
const command = parseFoundryCommand(comment.body ?? '', config);
|
|
123
|
+
if (!command)
|
|
124
|
+
return [];
|
|
125
|
+
const issueNumber = issue.number;
|
|
126
|
+
const task = state.getAllTasks(config.repo).find(t => t.issue === issueNumber) ?? null;
|
|
127
|
+
return [{
|
|
128
|
+
type: 'command',
|
|
129
|
+
issue: issueNumber,
|
|
130
|
+
task,
|
|
131
|
+
command: command.name,
|
|
132
|
+
message: command.message,
|
|
133
|
+
commentId: comment.id,
|
|
134
|
+
commentAuthor: author,
|
|
135
|
+
via: 'comment',
|
|
136
|
+
}];
|
|
137
|
+
}
|
|
138
|
+
// ── workflow_dispatch ───────────────────────────────────────────────────
|
|
139
|
+
/**
|
|
140
|
+
* A command delivered by `gh workflow run` with inputs {issue, command,
|
|
141
|
+
* message}. This is how Foundry hands work to itself across jobs, since
|
|
142
|
+
* workflow_dispatch is delivered even when the job's own token caused it.
|
|
143
|
+
*/
|
|
144
|
+
function mapWorkflowDispatch(payload, config) {
|
|
145
|
+
const inputs = payload.inputs ?? {};
|
|
146
|
+
const issueNumber = parseInt(String(inputs.issue ?? ''), 10);
|
|
147
|
+
if (!Number.isFinite(issueNumber))
|
|
148
|
+
return [];
|
|
149
|
+
const name = String(inputs.command ?? '');
|
|
150
|
+
if (!(name in config.comment_triggers))
|
|
151
|
+
return [];
|
|
152
|
+
const trigger = config.comment_triggers[name];
|
|
153
|
+
const body = inputs.message ? `${trigger}\n${inputs.message}` : trigger;
|
|
154
|
+
const command = parseFoundryCommand(body, config);
|
|
155
|
+
if (!command)
|
|
156
|
+
return [];
|
|
157
|
+
const task = state.getAllTasks(config.repo).find(t => t.issue === issueNumber) ?? null;
|
|
158
|
+
return [{
|
|
159
|
+
type: 'command',
|
|
160
|
+
issue: issueNumber,
|
|
161
|
+
task,
|
|
162
|
+
command: command.name,
|
|
163
|
+
message: command.message,
|
|
164
|
+
commentId: 0,
|
|
165
|
+
commentAuthor: payload.sender?.login ?? 'workflow_dispatch',
|
|
166
|
+
via: 'dispatch',
|
|
167
|
+
}];
|
|
168
|
+
}
|
|
169
|
+
// ── pull_request.closed (merged) ────────────────────────────────────────
|
|
170
|
+
function mapPullRequestClosed(payload, config) {
|
|
171
|
+
const pr = payload.pull_request;
|
|
172
|
+
if (!pr)
|
|
173
|
+
return [];
|
|
174
|
+
const branch = pr.head?.ref ?? '';
|
|
175
|
+
const repo = config.repo;
|
|
176
|
+
// A task's PR: completion on merge; a close without merge is a human
|
|
177
|
+
// decision Foundry leaves alone.
|
|
178
|
+
const task = state.getAllTasks(repo).find(t => t.branch === branch);
|
|
179
|
+
if (task)
|
|
180
|
+
return pr.merged ? [{ type: 'pr_merged', task, base: pr.base?.ref }] : [];
|
|
181
|
+
// Any other PR with a listed base: its preview comes down, merged or not.
|
|
182
|
+
return mapPullRequestPreview(payload, config, 'down');
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* A pull request that is not a task but whose base is listed in
|
|
186
|
+
* `preview.pull_request_bases` gets a preview of its own.
|
|
187
|
+
*/
|
|
188
|
+
function mapPullRequestPreview(payload, config, action) {
|
|
189
|
+
const pr = payload.pull_request;
|
|
190
|
+
if (!pr)
|
|
191
|
+
return [];
|
|
192
|
+
const bases = config.preview?.pull_request_bases ?? [];
|
|
193
|
+
const base = pr.base?.ref ?? '';
|
|
194
|
+
if (!bases.includes(base))
|
|
195
|
+
return [];
|
|
196
|
+
const branch = pr.head?.ref ?? '';
|
|
197
|
+
// A task's own PR is previewed through the task lifecycle, never twice.
|
|
198
|
+
if (state.getAllTasks(config.repo).some(t => t.branch === branch))
|
|
199
|
+
return [];
|
|
200
|
+
return [{
|
|
201
|
+
type: 'pr_preview',
|
|
202
|
+
action,
|
|
203
|
+
pr_number: pr.number,
|
|
204
|
+
branch,
|
|
205
|
+
base,
|
|
206
|
+
sha: pr.head?.sha ?? '',
|
|
207
|
+
}];
|
|
208
|
+
}
|
|
209
|
+
// ── pull_request_review.submitted ───────────────────────────────────────
|
|
210
|
+
function mapPullRequestReview(payload, config) {
|
|
211
|
+
const review = payload.review;
|
|
212
|
+
const pr = payload.pull_request;
|
|
213
|
+
if (!review || !pr)
|
|
214
|
+
return [];
|
|
215
|
+
const branch = pr.head?.ref ?? '';
|
|
216
|
+
const base = pr.base?.ref ?? '';
|
|
217
|
+
const repo = config.repo;
|
|
218
|
+
const task = state.getAllTasks(repo).find(t => t.branch === branch);
|
|
219
|
+
if (review.state === 'changes_requested') {
|
|
220
|
+
if (!task)
|
|
221
|
+
return [];
|
|
222
|
+
return [{ type: 'pr_review', task, feedback: buildReviewFeedback(review) }];
|
|
223
|
+
}
|
|
224
|
+
if (review.state === 'approved' && config.review?.merge_on_approval !== false) {
|
|
225
|
+
const promotion = (config.preview?.pull_request_bases ?? []).includes(base);
|
|
226
|
+
if (!task && !promotion)
|
|
227
|
+
return [];
|
|
228
|
+
return [{
|
|
229
|
+
type: 'pr_approved',
|
|
230
|
+
pr_number: pr.number,
|
|
231
|
+
branch,
|
|
232
|
+
base,
|
|
233
|
+
reviewer: review.user?.login ?? 'unknown',
|
|
234
|
+
...(task ? { task } : {}),
|
|
235
|
+
}];
|
|
236
|
+
}
|
|
237
|
+
return [];
|
|
238
|
+
}
|
|
239
|
+
function buildReviewFeedback(review) {
|
|
240
|
+
const parts = ['PR review feedback for your changes:'];
|
|
241
|
+
const author = review.user?.login ?? 'unknown';
|
|
242
|
+
parts.push(`\n**Review by ${author} (changes requested):**`);
|
|
243
|
+
if (review.body)
|
|
244
|
+
parts.push(review.body);
|
|
245
|
+
parts.push('\nPlease address the review feedback, commit your changes, and push.');
|
|
246
|
+
return parts.join('\n');
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=webhook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/lib/webhook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker interface — how an agent process is executed.
|
|
3
|
+
*
|
|
4
|
+
* Implementation: SubprocessWorker (agent as a child of the job).
|
|
5
|
+
* The interface is kept so another execution model can be added later.
|
|
6
|
+
*/
|
|
7
|
+
export interface WorkerHandle {
|
|
8
|
+
/** Unique worker identifier (e.g. `foundry-42`) */
|
|
9
|
+
id: string;
|
|
10
|
+
/** Check if the worker process is still running */
|
|
11
|
+
isRunning(): Promise<boolean>;
|
|
12
|
+
/** Kill the worker process */
|
|
13
|
+
kill(): Promise<void>;
|
|
14
|
+
/** Capture recent output from the worker */
|
|
15
|
+
getLogs(lines?: number): Promise<string>;
|
|
16
|
+
/** Interactively attach to the worker (optional — not all backends support it) */
|
|
17
|
+
attach?(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Wait for the worker to exit and resolve with its exit code (optional —
|
|
20
|
+
* only in-process workers can offer this). Null if unknown or killed.
|
|
21
|
+
*/
|
|
22
|
+
wait?(): Promise<number | null>;
|
|
23
|
+
}
|
|
24
|
+
export interface WorkerSpawnOpts {
|
|
25
|
+
/** Session/container name */
|
|
26
|
+
id: string;
|
|
27
|
+
/** Working directory */
|
|
28
|
+
cwd: string;
|
|
29
|
+
/** Command to execute */
|
|
30
|
+
command: string;
|
|
31
|
+
/** Environment variables to set before running the command */
|
|
32
|
+
env?: Record<string, string>;
|
|
33
|
+
}
|
|
34
|
+
export interface Worker {
|
|
35
|
+
/** Worker backend name (e.g. 'subprocess') */
|
|
36
|
+
name: string;
|
|
37
|
+
/** Spawn a new worker process and return a handle to it */
|
|
38
|
+
spawn(opts: WorkerSpawnOpts): Promise<WorkerHandle>;
|
|
39
|
+
/** Get a handle for an existing worker by id (e.g. reconnect after restart) */
|
|
40
|
+
handleFor(id: string): WorkerHandle;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/lib/worker.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,YAAY;IAC3B,mDAAmD;IACnD,EAAE,EAAE,MAAM,CAAC;IAEX,mDAAmD;IACnD,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAE9B,8BAA8B;IAC9B,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtB,4CAA4C;IAC5C,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAEzC,kFAAkF;IAClF,MAAM,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzB;;;OAGG;IACH,IAAI,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,EAAE,EAAE,MAAM,CAAC;IAEX,wBAAwB;IACxB,GAAG,EAAE,MAAM,CAAC;IAEZ,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAEhB,8DAA8D;IAC9D,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,MAAM;IACrB,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAC;IAEb,2DAA2D;IAC3D,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAEpD,+EAA+E;IAC/E,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,CAAC;CACrC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Worker interface — how an agent process is executed.
|
|
4
|
+
*
|
|
5
|
+
* Implementation: SubprocessWorker (agent as a child of the job).
|
|
6
|
+
* The interface is kept so another execution model can be added later.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/lib/worker.ts"],"names":[],"mappings":";AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker registry — resolves a worker type to a Worker implementation.
|
|
3
|
+
*
|
|
4
|
+
* Only `subprocess` exists: the agent runs as a child of the current process,
|
|
5
|
+
* which under the GitHub Action means the job is the isolation boundary. The
|
|
6
|
+
* Worker interface is kept so another execution model can be added without
|
|
7
|
+
* touching the EventHandler.
|
|
8
|
+
*/
|
|
9
|
+
import type { Worker } from '../worker.js';
|
|
10
|
+
export declare function resolveWorker(type?: string): Worker;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/workers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAW3C,wBAAgB,aAAa,CAAC,IAAI,GAAE,MAAqB,GAAG,MAAM,CAQjE"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveWorker = resolveWorker;
|
|
4
|
+
const subprocess_js_1 = require("./subprocess.js");
|
|
5
|
+
// The subprocess worker tracks children in memory, so it must be a singleton
|
|
6
|
+
// within the process or handleFor() would lose them.
|
|
7
|
+
let subprocessSingleton;
|
|
8
|
+
const workers = {
|
|
9
|
+
subprocess: () => (subprocessSingleton ??= new subprocess_js_1.SubprocessWorker()),
|
|
10
|
+
};
|
|
11
|
+
function resolveWorker(type = 'subprocess') {
|
|
12
|
+
const factory = workers[type];
|
|
13
|
+
if (!factory) {
|
|
14
|
+
throw new Error(`Unknown worker type "${type}". Available: ${Object.keys(workers).join(', ')}`);
|
|
15
|
+
}
|
|
16
|
+
return factory();
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/workers/index.ts"],"names":[],"mappings":";;AAmBA,sCAQC;AAlBD,mDAAmD;AAEnD,6EAA6E;AAC7E,qDAAqD;AACrD,IAAI,mBAAiD,CAAC;AAEtD,MAAM,OAAO,GAAiC;IAC5C,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,mBAAmB,KAAK,IAAI,gCAAgB,EAAE,CAAC;CACnE,CAAC;AAEF,SAAgB,aAAa,CAAC,OAAe,YAAY;IACvD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,wBAAwB,IAAI,iBAAiB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC/E,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,EAAE,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Worker, WorkerHandle, WorkerSpawnOpts } from '../worker.js';
|
|
2
|
+
export declare class SubprocessWorker implements Worker {
|
|
3
|
+
readonly name = "subprocess";
|
|
4
|
+
private readonly tracked;
|
|
5
|
+
handleFor(id: string): WorkerHandle;
|
|
6
|
+
spawn(opts: WorkerSpawnOpts): Promise<WorkerHandle>;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=subprocess.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subprocess.d.ts","sourceRoot":"","sources":["../../../src/lib/workers/subprocess.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AA2C1E,qBAAa,gBAAiB,YAAW,MAAM;IAC7C,QAAQ,CAAC,IAAI,gBAAgB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IAEtD,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY;IAI7B,KAAK,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,YAAY,CAAC;CA8C1D"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SubprocessWorker = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* SubprocessWorker — runs the agent as a child process of the current
|
|
6
|
+
* Node process, streaming its output to stdout.
|
|
7
|
+
*
|
|
8
|
+
* This is the worker for `foundry action`, where the GitHub Actions job is
|
|
9
|
+
* the isolation boundary and nothing needs to outlive the process. There is
|
|
10
|
+
* no tmux, no detach, no reattach: the job waits on the child directly.
|
|
11
|
+
*
|
|
12
|
+
* Handles are tracked in-memory for the lifetime of the process. `handleFor`
|
|
13
|
+
* on an id this process never spawned returns a handle that reports
|
|
14
|
+
* not-running, which is the correct answer inside a fresh job.
|
|
15
|
+
*/
|
|
16
|
+
const node_child_process_1 = require("node:child_process");
|
|
17
|
+
const MAX_BUFFERED_LINES = 2000;
|
|
18
|
+
const KILL_GRACE_MS = 5_000;
|
|
19
|
+
class SubprocessHandle {
|
|
20
|
+
id;
|
|
21
|
+
tracked;
|
|
22
|
+
constructor(id, tracked) {
|
|
23
|
+
this.id = id;
|
|
24
|
+
this.tracked = tracked;
|
|
25
|
+
}
|
|
26
|
+
async isRunning() {
|
|
27
|
+
return this.tracked ? !this.tracked.exited : false;
|
|
28
|
+
}
|
|
29
|
+
async kill() {
|
|
30
|
+
const t = this.tracked;
|
|
31
|
+
if (!t || t.exited)
|
|
32
|
+
return;
|
|
33
|
+
t.child.kill('SIGTERM');
|
|
34
|
+
const timer = setTimeout(() => {
|
|
35
|
+
if (!t.exited)
|
|
36
|
+
t.child.kill('SIGKILL');
|
|
37
|
+
}, KILL_GRACE_MS);
|
|
38
|
+
await t.done;
|
|
39
|
+
clearTimeout(timer);
|
|
40
|
+
}
|
|
41
|
+
async getLogs(lines = 50) {
|
|
42
|
+
if (!this.tracked)
|
|
43
|
+
return '';
|
|
44
|
+
return this.tracked.lines.slice(-lines).join('\n');
|
|
45
|
+
}
|
|
46
|
+
/** Resolve with the exit code once the child exits. Null if killed by signal. */
|
|
47
|
+
async wait() {
|
|
48
|
+
if (!this.tracked)
|
|
49
|
+
return null;
|
|
50
|
+
return this.tracked.done;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
class SubprocessWorker {
|
|
54
|
+
name = 'subprocess';
|
|
55
|
+
tracked = new Map();
|
|
56
|
+
handleFor(id) {
|
|
57
|
+
return new SubprocessHandle(id, this.tracked.get(id));
|
|
58
|
+
}
|
|
59
|
+
async spawn(opts) {
|
|
60
|
+
const existing = this.tracked.get(opts.id);
|
|
61
|
+
if (existing && !existing.exited) {
|
|
62
|
+
throw new Error(`Worker "${opts.id}" is already running.`);
|
|
63
|
+
}
|
|
64
|
+
const child = (0, node_child_process_1.spawn)('bash', ['-lc', opts.command], {
|
|
65
|
+
cwd: opts.cwd,
|
|
66
|
+
env: { ...process.env, ...(opts.env ?? {}) },
|
|
67
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
68
|
+
});
|
|
69
|
+
const lines = [];
|
|
70
|
+
const record = (chunk, sink) => {
|
|
71
|
+
sink.write(chunk);
|
|
72
|
+
for (const line of chunk.toString('utf-8').split('\n')) {
|
|
73
|
+
if (line.length === 0)
|
|
74
|
+
continue;
|
|
75
|
+
lines.push(line);
|
|
76
|
+
if (lines.length > MAX_BUFFERED_LINES)
|
|
77
|
+
lines.shift();
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
child.stdout?.on('data', (c) => record(c, process.stdout));
|
|
81
|
+
child.stderr?.on('data', (c) => record(c, process.stderr));
|
|
82
|
+
const entry = {
|
|
83
|
+
child,
|
|
84
|
+
exited: false,
|
|
85
|
+
exitCode: null,
|
|
86
|
+
lines,
|
|
87
|
+
done: new Promise(resolve => {
|
|
88
|
+
child.on('error', () => {
|
|
89
|
+
entry.exited = true;
|
|
90
|
+
entry.exitCode = null;
|
|
91
|
+
resolve(null);
|
|
92
|
+
});
|
|
93
|
+
child.on('exit', (code) => {
|
|
94
|
+
entry.exited = true;
|
|
95
|
+
entry.exitCode = code;
|
|
96
|
+
resolve(code);
|
|
97
|
+
});
|
|
98
|
+
}),
|
|
99
|
+
};
|
|
100
|
+
this.tracked.set(opts.id, entry);
|
|
101
|
+
return new SubprocessHandle(opts.id, entry);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.SubprocessWorker = SubprocessWorker;
|
|
105
|
+
//# sourceMappingURL=subprocess.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subprocess.js","sourceRoot":"","sources":["../../../src/lib/workers/subprocess.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { FoundryConfig, TaskState } from '../types.js';
|
|
2
|
+
export interface PreserveResult {
|
|
3
|
+
/** A commit was made for uncommitted changes. */
|
|
4
|
+
committed: boolean;
|
|
5
|
+
/** The branch was pushed (it had commits beyond its base). */
|
|
6
|
+
pushed: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Make the agent's work survive the end of this job: commit anything
|
|
10
|
+
* uncommitted, then push the branch if it has commits beyond its base.
|
|
11
|
+
* Never throws; a failure is logged and reported in the result so the
|
|
12
|
+
* status comment can say so.
|
|
13
|
+
*/
|
|
14
|
+
export declare function preserveWork(config: FoundryConfig, task: TaskState, repoDir: string, reason: string): PreserveResult;
|
|
15
|
+
/**
|
|
16
|
+
* Make sure the task's worktree exists before an agent is launched into it.
|
|
17
|
+
* In a fresh job it is recreated from the pushed branch; if the branch was
|
|
18
|
+
* never pushed, from the base branch.
|
|
19
|
+
*/
|
|
20
|
+
export declare function ensureWorktree(config: FoundryConfig, task: TaskState, repoDir: string): void;
|
|
21
|
+
//# sourceMappingURL=worktree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/lib/worktree.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE5D,MAAM,WAAW,cAAc;IAC7B,iDAAiD;IACjD,SAAS,EAAE,OAAO,CAAC;IACnB,8DAA8D;IAC9D,MAAM,EAAE,OAAO,CAAC;CACjB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,cAAc,CA2BpH;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAmB5F"}
|