@mastra/factory 0.2.1-alpha.2 → 0.2.1-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +3462 -3583
- package/dist/factory.js.map +1 -1
- package/dist/index.js +3462 -3583
- package/dist/index.js.map +1 -1
- package/dist/integrations/base.d.ts +13 -25
- package/dist/integrations/base.d.ts.map +1 -1
- package/dist/integrations/github/integration.d.ts.map +1 -1
- package/dist/integrations/github/integration.js +625 -217
- package/dist/integrations/github/integration.js.map +1 -1
- package/dist/integrations/github/routes.d.ts +1 -4
- package/dist/integrations/github/routes.d.ts.map +1 -1
- package/dist/integrations/github/routes.js +113 -203
- package/dist/integrations/github/routes.js.map +1 -1
- package/dist/integrations/github/rules.d.ts +30 -0
- package/dist/integrations/github/rules.d.ts.map +1 -0
- package/dist/{rules/github-service.js → integrations/github/rules.js} +27 -8
- package/dist/integrations/github/rules.js.map +1 -0
- package/dist/integrations/linear/agent-tools.js.map +1 -1
- package/dist/integrations/linear/integration.d.ts.map +1 -1
- package/dist/integrations/linear/integration.js +352 -3
- package/dist/integrations/linear/integration.js.map +1 -1
- package/dist/integrations/linear/routes.d.ts +2 -2
- package/dist/integrations/linear/routes.d.ts.map +1 -1
- package/dist/integrations/linear/routes.js +2 -2
- package/dist/integrations/linear/routes.js.map +1 -1
- package/dist/integrations/linear/rules.d.ts +42 -0
- package/dist/integrations/linear/rules.d.ts.map +1 -0
- package/dist/{rules/linear-service.js → integrations/linear/rules.js} +14 -4
- package/dist/integrations/linear/rules.js.map +1 -0
- package/dist/integrations/platform/github/integration.d.ts.map +1 -1
- package/dist/integrations/platform/github/integration.js +626 -218
- package/dist/integrations/platform/github/integration.js.map +1 -1
- package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
- package/dist/integrations/platform/linear/integration.js +353 -3
- package/dist/integrations/platform/linear/integration.js.map +1 -1
- package/dist/routes/oauth.js +6 -39
- package/dist/routes/oauth.js.map +1 -1
- package/dist/routes/surface.d.ts +3 -1
- package/dist/routes/surface.d.ts.map +1 -1
- package/dist/routes/surface.js +230 -619
- package/dist/routes/surface.js.map +1 -1
- package/dist/routes/work-items.js.map +1 -1
- package/dist/storage/domains/work-items/base.d.ts.map +1 -1
- package/dist/storage/domains/work-items/base.js +74 -75
- package/dist/storage/domains/work-items/base.js.map +1 -1
- package/dist/storage/domains/work-items/metrics.js.map +1 -1
- package/package.json +5 -5
- package/dist/integrations/github/project-lock.d.ts +0 -100
- package/dist/integrations/github/project-lock.d.ts.map +0 -1
- package/dist/integrations/github/project-lock.js +0 -103
- package/dist/integrations/github/project-lock.js.map +0 -1
- package/dist/rules/github-service.d.ts +0 -29
- package/dist/rules/github-service.d.ts.map +0 -1
- package/dist/rules/github-service.js.map +0 -1
- package/dist/rules/linear-service.d.ts +0 -27
- package/dist/rules/linear-service.d.ts.map +0 -1
- package/dist/rules/linear-service.js.map +0 -1
package/dist/routes/surface.js
CHANGED
|
@@ -5797,7 +5797,7 @@ var init_errors = __esm({
|
|
|
5797
5797
|
});
|
|
5798
5798
|
|
|
5799
5799
|
// ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@libsql/hrana-client/0.10.0/56906f702e597dd372b3dd88d4aef2fcfb8f7d209d434be1f2455f1e7f8c6772/node_modules/@libsql/hrana-client/lib-esm/encoding/json/decode.js
|
|
5800
|
-
function
|
|
5800
|
+
function string(value) {
|
|
5801
5801
|
if (typeof value === "string") {
|
|
5802
5802
|
return value;
|
|
5803
5803
|
}
|
|
@@ -5811,13 +5811,13 @@ function stringOpt(value) {
|
|
|
5811
5811
|
}
|
|
5812
5812
|
throw typeError(value, "string or null");
|
|
5813
5813
|
}
|
|
5814
|
-
function
|
|
5814
|
+
function number(value) {
|
|
5815
5815
|
if (typeof value === "number") {
|
|
5816
5816
|
return value;
|
|
5817
5817
|
}
|
|
5818
5818
|
throw typeError(value, "number");
|
|
5819
5819
|
}
|
|
5820
|
-
function
|
|
5820
|
+
function boolean(value) {
|
|
5821
5821
|
if (typeof value === "boolean") {
|
|
5822
5822
|
return value;
|
|
5823
5823
|
}
|
|
@@ -5829,14 +5829,14 @@ function array(value) {
|
|
|
5829
5829
|
}
|
|
5830
5830
|
throw typeError(value, "array");
|
|
5831
5831
|
}
|
|
5832
|
-
function
|
|
5832
|
+
function object(value) {
|
|
5833
5833
|
if (value !== null && typeof value === "object" && !Array.isArray(value)) {
|
|
5834
5834
|
return value;
|
|
5835
5835
|
}
|
|
5836
5836
|
throw typeError(value, "object");
|
|
5837
5837
|
}
|
|
5838
5838
|
function arrayObjectsMap(value, fun) {
|
|
5839
|
-
return array(value).map((elemValue) => fun(
|
|
5839
|
+
return array(value).map((elemValue) => fun(object(elemValue)));
|
|
5840
5840
|
}
|
|
5841
5841
|
function typeError(value, expected) {
|
|
5842
5842
|
if (value === void 0) {
|
|
@@ -5851,7 +5851,7 @@ function typeError(value, expected) {
|
|
|
5851
5851
|
return new ProtoError(`Expected ${expected}, received ${received}`);
|
|
5852
5852
|
}
|
|
5853
5853
|
function readJsonObject(value, fun) {
|
|
5854
|
-
return fun(
|
|
5854
|
+
return fun(object(value));
|
|
5855
5855
|
}
|
|
5856
5856
|
var init_decode = __esm({
|
|
5857
5857
|
"../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@libsql/hrana-client/0.10.0/56906f702e597dd372b3dd88d4aef2fcfb8f7d209d434be1f2455f1e7f8c6772/node_modules/@libsql/hrana-client/lib-esm/encoding/json/decode.js"() {
|
|
@@ -7531,14 +7531,14 @@ var init_protobuf_encode2 = __esm({
|
|
|
7531
7531
|
|
|
7532
7532
|
// ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@libsql/hrana-client/0.10.0/56906f702e597dd372b3dd88d4aef2fcfb8f7d209d434be1f2455f1e7f8c6772/node_modules/@libsql/hrana-client/lib-esm/shared/json_decode.js
|
|
7533
7533
|
function Error2(obj) {
|
|
7534
|
-
const message =
|
|
7534
|
+
const message = string(obj["message"]);
|
|
7535
7535
|
const code = stringOpt(obj["code"]);
|
|
7536
7536
|
return { message, code };
|
|
7537
7537
|
}
|
|
7538
7538
|
function StmtResult(obj) {
|
|
7539
7539
|
const cols = arrayObjectsMap(obj["cols"], Col);
|
|
7540
7540
|
const rows = array(obj["rows"]).map((rowObj) => arrayObjectsMap(rowObj, Value3));
|
|
7541
|
-
const affectedRowCount =
|
|
7541
|
+
const affectedRowCount = number(obj["affected_row_count"]);
|
|
7542
7542
|
const lastInsertRowidStr = stringOpt(obj["last_insert_rowid"]);
|
|
7543
7543
|
const lastInsertRowid = lastInsertRowidStr !== void 0 ? BigInt(lastInsertRowidStr) : void 0;
|
|
7544
7544
|
return { cols, rows, affectedRowCount, lastInsertRowid };
|
|
@@ -7552,37 +7552,37 @@ function BatchResult(obj) {
|
|
|
7552
7552
|
const stepResults = /* @__PURE__ */ new Map();
|
|
7553
7553
|
array(obj["step_results"]).forEach((value, i) => {
|
|
7554
7554
|
if (value !== null) {
|
|
7555
|
-
stepResults.set(i, StmtResult(
|
|
7555
|
+
stepResults.set(i, StmtResult(object(value)));
|
|
7556
7556
|
}
|
|
7557
7557
|
});
|
|
7558
7558
|
const stepErrors = /* @__PURE__ */ new Map();
|
|
7559
7559
|
array(obj["step_errors"]).forEach((value, i) => {
|
|
7560
7560
|
if (value !== null) {
|
|
7561
|
-
stepErrors.set(i, Error2(
|
|
7561
|
+
stepErrors.set(i, Error2(object(value)));
|
|
7562
7562
|
}
|
|
7563
7563
|
});
|
|
7564
7564
|
return { stepResults, stepErrors };
|
|
7565
7565
|
}
|
|
7566
7566
|
function CursorEntry(obj) {
|
|
7567
|
-
const type =
|
|
7567
|
+
const type = string(obj["type"]);
|
|
7568
7568
|
if (type === "step_begin") {
|
|
7569
|
-
const step =
|
|
7569
|
+
const step = number(obj["step"]);
|
|
7570
7570
|
const cols = arrayObjectsMap(obj["cols"], Col);
|
|
7571
7571
|
return { type: "step_begin", step, cols };
|
|
7572
7572
|
} else if (type === "step_end") {
|
|
7573
|
-
const affectedRowCount =
|
|
7573
|
+
const affectedRowCount = number(obj["affected_row_count"]);
|
|
7574
7574
|
const lastInsertRowidStr = stringOpt(obj["last_insert_rowid"]);
|
|
7575
7575
|
const lastInsertRowid = lastInsertRowidStr !== void 0 ? BigInt(lastInsertRowidStr) : void 0;
|
|
7576
7576
|
return { type: "step_end", affectedRowCount, lastInsertRowid };
|
|
7577
7577
|
} else if (type === "step_error") {
|
|
7578
|
-
const step =
|
|
7579
|
-
const error = Error2(
|
|
7578
|
+
const step = number(obj["step"]);
|
|
7579
|
+
const error = Error2(object(obj["error"]));
|
|
7580
7580
|
return { type: "step_error", step, error };
|
|
7581
7581
|
} else if (type === "row") {
|
|
7582
7582
|
const row = arrayObjectsMap(obj["row"], Value3);
|
|
7583
7583
|
return { type: "row", row };
|
|
7584
7584
|
} else if (type === "error") {
|
|
7585
|
-
const error = Error2(
|
|
7585
|
+
const error = Error2(object(obj["error"]));
|
|
7586
7586
|
return { type: "error", error };
|
|
7587
7587
|
} else {
|
|
7588
7588
|
throw new ProtoError("Unexpected type of CursorEntry");
|
|
@@ -7591,8 +7591,8 @@ function CursorEntry(obj) {
|
|
|
7591
7591
|
function DescribeResult(obj) {
|
|
7592
7592
|
const params = arrayObjectsMap(obj["params"], DescribeParam);
|
|
7593
7593
|
const cols = arrayObjectsMap(obj["cols"], DescribeCol);
|
|
7594
|
-
const isExplain =
|
|
7595
|
-
const isReadonly =
|
|
7594
|
+
const isExplain = boolean(obj["is_explain"]);
|
|
7595
|
+
const isReadonly = boolean(obj["is_readonly"]);
|
|
7596
7596
|
return { params, cols, isExplain, isReadonly };
|
|
7597
7597
|
}
|
|
7598
7598
|
function DescribeParam(obj) {
|
|
@@ -7600,23 +7600,23 @@ function DescribeParam(obj) {
|
|
|
7600
7600
|
return { name };
|
|
7601
7601
|
}
|
|
7602
7602
|
function DescribeCol(obj) {
|
|
7603
|
-
const name =
|
|
7603
|
+
const name = string(obj["name"]);
|
|
7604
7604
|
const decltype = stringOpt(obj["decltype"]);
|
|
7605
7605
|
return { name, decltype };
|
|
7606
7606
|
}
|
|
7607
7607
|
function Value3(obj) {
|
|
7608
|
-
const type =
|
|
7608
|
+
const type = string(obj["type"]);
|
|
7609
7609
|
if (type === "null") {
|
|
7610
7610
|
return null;
|
|
7611
7611
|
} else if (type === "integer") {
|
|
7612
|
-
const value =
|
|
7612
|
+
const value = string(obj["value"]);
|
|
7613
7613
|
return BigInt(value);
|
|
7614
7614
|
} else if (type === "float") {
|
|
7615
|
-
return
|
|
7615
|
+
return number(obj["value"]);
|
|
7616
7616
|
} else if (type === "text") {
|
|
7617
|
-
return
|
|
7617
|
+
return string(obj["value"]);
|
|
7618
7618
|
} else if (type === "blob") {
|
|
7619
|
-
return gBase64.toUint8Array(
|
|
7619
|
+
return gBase64.toUint8Array(string(obj["base64"]));
|
|
7620
7620
|
} else {
|
|
7621
7621
|
throw new ProtoError("Unexpected type of Value");
|
|
7622
7622
|
}
|
|
@@ -7632,35 +7632,35 @@ var init_json_decode = __esm({
|
|
|
7632
7632
|
|
|
7633
7633
|
// ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@libsql/hrana-client/0.10.0/56906f702e597dd372b3dd88d4aef2fcfb8f7d209d434be1f2455f1e7f8c6772/node_modules/@libsql/hrana-client/lib-esm/ws/json_decode.js
|
|
7634
7634
|
function ServerMsg(obj) {
|
|
7635
|
-
const type =
|
|
7635
|
+
const type = string(obj["type"]);
|
|
7636
7636
|
if (type === "hello_ok") {
|
|
7637
7637
|
return { type: "hello_ok" };
|
|
7638
7638
|
} else if (type === "hello_error") {
|
|
7639
|
-
const error = Error2(
|
|
7639
|
+
const error = Error2(object(obj["error"]));
|
|
7640
7640
|
return { type: "hello_error", error };
|
|
7641
7641
|
} else if (type === "response_ok") {
|
|
7642
|
-
const requestId =
|
|
7643
|
-
const response = Response(
|
|
7642
|
+
const requestId = number(obj["request_id"]);
|
|
7643
|
+
const response = Response(object(obj["response"]));
|
|
7644
7644
|
return { type: "response_ok", requestId, response };
|
|
7645
7645
|
} else if (type === "response_error") {
|
|
7646
|
-
const requestId =
|
|
7647
|
-
const error = Error2(
|
|
7646
|
+
const requestId = number(obj["request_id"]);
|
|
7647
|
+
const error = Error2(object(obj["error"]));
|
|
7648
7648
|
return { type: "response_error", requestId, error };
|
|
7649
7649
|
} else {
|
|
7650
7650
|
throw new ProtoError("Unexpected type of ServerMsg");
|
|
7651
7651
|
}
|
|
7652
7652
|
}
|
|
7653
7653
|
function Response(obj) {
|
|
7654
|
-
const type =
|
|
7654
|
+
const type = string(obj["type"]);
|
|
7655
7655
|
if (type === "open_stream") {
|
|
7656
7656
|
return { type: "open_stream" };
|
|
7657
7657
|
} else if (type === "close_stream") {
|
|
7658
7658
|
return { type: "close_stream" };
|
|
7659
7659
|
} else if (type === "execute") {
|
|
7660
|
-
const result = StmtResult(
|
|
7660
|
+
const result = StmtResult(object(obj["result"]));
|
|
7661
7661
|
return { type: "execute", result };
|
|
7662
7662
|
} else if (type === "batch") {
|
|
7663
|
-
const result = BatchResult(
|
|
7663
|
+
const result = BatchResult(object(obj["result"]));
|
|
7664
7664
|
return { type: "batch", result };
|
|
7665
7665
|
} else if (type === "open_cursor") {
|
|
7666
7666
|
return { type: "open_cursor" };
|
|
@@ -7668,19 +7668,19 @@ function Response(obj) {
|
|
|
7668
7668
|
return { type: "close_cursor" };
|
|
7669
7669
|
} else if (type === "fetch_cursor") {
|
|
7670
7670
|
const entries = arrayObjectsMap(obj["entries"], CursorEntry);
|
|
7671
|
-
const done =
|
|
7671
|
+
const done = boolean(obj["done"]);
|
|
7672
7672
|
return { type: "fetch_cursor", entries, done };
|
|
7673
7673
|
} else if (type === "sequence") {
|
|
7674
7674
|
return { type: "sequence" };
|
|
7675
7675
|
} else if (type === "describe") {
|
|
7676
|
-
const result = DescribeResult(
|
|
7676
|
+
const result = DescribeResult(object(obj["result"]));
|
|
7677
7677
|
return { type: "describe", result };
|
|
7678
7678
|
} else if (type === "store_sql") {
|
|
7679
7679
|
return { type: "store_sql" };
|
|
7680
7680
|
} else if (type === "close_sql") {
|
|
7681
7681
|
return { type: "close_sql" };
|
|
7682
7682
|
} else if (type === "get_autocommit") {
|
|
7683
|
-
const isAutocommit =
|
|
7683
|
+
const isAutocommit = boolean(obj["is_autocommit"]);
|
|
7684
7684
|
return { type: "get_autocommit", isAutocommit };
|
|
7685
7685
|
} else {
|
|
7686
7686
|
throw new ProtoError("Unexpected type of Response");
|
|
@@ -8427,38 +8427,38 @@ function PipelineRespBody(obj) {
|
|
|
8427
8427
|
return { baton, baseUrl, results };
|
|
8428
8428
|
}
|
|
8429
8429
|
function StreamResult(obj) {
|
|
8430
|
-
const type =
|
|
8430
|
+
const type = string(obj["type"]);
|
|
8431
8431
|
if (type === "ok") {
|
|
8432
|
-
const response = StreamResponse(
|
|
8432
|
+
const response = StreamResponse(object(obj["response"]));
|
|
8433
8433
|
return { type: "ok", response };
|
|
8434
8434
|
} else if (type === "error") {
|
|
8435
|
-
const error = Error2(
|
|
8435
|
+
const error = Error2(object(obj["error"]));
|
|
8436
8436
|
return { type: "error", error };
|
|
8437
8437
|
} else {
|
|
8438
8438
|
throw new ProtoError("Unexpected type of StreamResult");
|
|
8439
8439
|
}
|
|
8440
8440
|
}
|
|
8441
8441
|
function StreamResponse(obj) {
|
|
8442
|
-
const type =
|
|
8442
|
+
const type = string(obj["type"]);
|
|
8443
8443
|
if (type === "close") {
|
|
8444
8444
|
return { type: "close" };
|
|
8445
8445
|
} else if (type === "execute") {
|
|
8446
|
-
const result = StmtResult(
|
|
8446
|
+
const result = StmtResult(object(obj["result"]));
|
|
8447
8447
|
return { type: "execute", result };
|
|
8448
8448
|
} else if (type === "batch") {
|
|
8449
|
-
const result = BatchResult(
|
|
8449
|
+
const result = BatchResult(object(obj["result"]));
|
|
8450
8450
|
return { type: "batch", result };
|
|
8451
8451
|
} else if (type === "sequence") {
|
|
8452
8452
|
return { type: "sequence" };
|
|
8453
8453
|
} else if (type === "describe") {
|
|
8454
|
-
const result = DescribeResult(
|
|
8454
|
+
const result = DescribeResult(object(obj["result"]));
|
|
8455
8455
|
return { type: "describe", result };
|
|
8456
8456
|
} else if (type === "store_sql") {
|
|
8457
8457
|
return { type: "store_sql" };
|
|
8458
8458
|
} else if (type === "close_sql") {
|
|
8459
8459
|
return { type: "close_sql" };
|
|
8460
8460
|
} else if (type === "get_autocommit") {
|
|
8461
|
-
const isAutocommit =
|
|
8461
|
+
const isAutocommit = boolean(obj["is_autocommit"]);
|
|
8462
8462
|
return { type: "get_autocommit", isAutocommit };
|
|
8463
8463
|
} else {
|
|
8464
8464
|
throw new ProtoError("Unexpected type of StreamResponse");
|
|
@@ -11628,29 +11628,14 @@ var init_dist = __esm({
|
|
|
11628
11628
|
this.vectorIndexes = this.isMemoryDb ? Promise.resolve(/* @__PURE__ */ new Set()) : this.discoverVectorIndexes();
|
|
11629
11629
|
}
|
|
11630
11630
|
/**
|
|
11631
|
-
* Closes the underlying libsql client, releasing
|
|
11632
|
-
*
|
|
11633
|
-
* For local file databases, first runs PRAGMA wal_checkpoint(TRUNCATE) and
|
|
11634
|
-
* switches back to journal_mode=DELETE so the -wal and -shm sidecar files
|
|
11635
|
-
* are released promptly (mirrors LibSQLStore.close()).
|
|
11636
|
-
*
|
|
11637
|
-
* Remote (Turso) databases skip the WAL pragmas and just close the client.
|
|
11631
|
+
* Closes the underlying libsql client, releasing this vector store's OS file handles.
|
|
11638
11632
|
*
|
|
11639
11633
|
* Safe to call more than once; subsequent calls are no-ops.
|
|
11640
11634
|
*/
|
|
11641
11635
|
async close() {
|
|
11642
|
-
if (this.turso.closed) {
|
|
11643
|
-
|
|
11636
|
+
if (!this.turso.closed) {
|
|
11637
|
+
this.turso.close();
|
|
11644
11638
|
}
|
|
11645
|
-
if (this.turso.protocol === "file" && !this.isMemoryDb) {
|
|
11646
|
-
try {
|
|
11647
|
-
await this.turso.execute("PRAGMA wal_checkpoint(TRUNCATE);");
|
|
11648
|
-
await this.turso.execute("PRAGMA journal_mode=DELETE;");
|
|
11649
|
-
} catch (err) {
|
|
11650
|
-
this.logger.warn("LibSQLVector: Failed to checkpoint WAL before close.", err);
|
|
11651
|
-
}
|
|
11652
|
-
}
|
|
11653
|
-
this.turso.close();
|
|
11654
11639
|
}
|
|
11655
11640
|
async discoverVectorIndexes() {
|
|
11656
11641
|
try {
|
|
@@ -24409,32 +24394,14 @@ ${unreflectedContent}` : bufferedReflection;
|
|
|
24409
24394
|
await this.initDomainsSequentially();
|
|
24410
24395
|
}
|
|
24411
24396
|
/**
|
|
24412
|
-
* Closes the underlying libsql client, releasing
|
|
24413
|
-
*
|
|
24414
|
-
* For local file databases, first runs PRAGMA wal_checkpoint(TRUNCATE) and
|
|
24415
|
-
* switches back to journal_mode=DELETE so that Windows releases the -wal
|
|
24416
|
-
* and -shm sidecar files promptly. Without this, the handles stay open
|
|
24417
|
-
* until process exit, causing EBUSY errors when callers try to fs.rm the
|
|
24418
|
-
* storage directory after Mastra.shutdown().
|
|
24419
|
-
*
|
|
24420
|
-
* Remote (Turso) databases skip the WAL pragmas and just close the client.
|
|
24397
|
+
* Closes the underlying libsql client, releasing this store's OS file handles.
|
|
24421
24398
|
*
|
|
24422
24399
|
* Safe to call more than once; subsequent calls are no-ops.
|
|
24423
24400
|
*/
|
|
24424
24401
|
async close() {
|
|
24425
|
-
if (this.client.closed) {
|
|
24426
|
-
|
|
24402
|
+
if (!this.client.closed) {
|
|
24403
|
+
this.client.close();
|
|
24427
24404
|
}
|
|
24428
|
-
const isLocalFileDb = this.isLocalDb || this.client.protocol === "file";
|
|
24429
|
-
if (isLocalFileDb) {
|
|
24430
|
-
try {
|
|
24431
|
-
await this.client.execute("PRAGMA wal_checkpoint(TRUNCATE);");
|
|
24432
|
-
await this.client.execute("PRAGMA journal_mode=DELETE;");
|
|
24433
|
-
} catch (err) {
|
|
24434
|
-
this.logger.warn("LibSQLStore: Failed to checkpoint WAL before close.", err);
|
|
24435
|
-
}
|
|
24436
|
-
}
|
|
24437
|
-
this.client.close();
|
|
24438
24405
|
}
|
|
24439
24406
|
};
|
|
24440
24407
|
LIBSQL_PROMPT = `When querying LibSQL Vector, you can ONLY use the operators listed below. Any other operators will be rejected.
|
|
@@ -24599,6 +24566,179 @@ async function ensureFactoryRuleSession(args) {
|
|
|
24599
24566
|
return { sessionId: session.sessionId, userId };
|
|
24600
24567
|
}
|
|
24601
24568
|
|
|
24569
|
+
// src/rules/start-coordinator.ts
|
|
24570
|
+
import { RequestContext } from "@mastra/core/request-context";
|
|
24571
|
+
import { formatSkillActivation } from "@mastra/core/workspace";
|
|
24572
|
+
var FactoryStartTransitionError = class extends Error {
|
|
24573
|
+
result;
|
|
24574
|
+
constructor(result) {
|
|
24575
|
+
super(result.reason);
|
|
24576
|
+
this.name = "FactoryStartTransitionError";
|
|
24577
|
+
this.result = result;
|
|
24578
|
+
}
|
|
24579
|
+
};
|
|
24580
|
+
function escapeSkillBoundary(value) {
|
|
24581
|
+
return value.replaceAll("</skill>", "</skill>");
|
|
24582
|
+
}
|
|
24583
|
+
async function resolveKickoffMessage(session, invocation) {
|
|
24584
|
+
if (!invocation) return null;
|
|
24585
|
+
if (invocation.type === "prompt") return invocation.prompt;
|
|
24586
|
+
const skills = session.getWorkspace().skills;
|
|
24587
|
+
await skills?.maybeRefresh();
|
|
24588
|
+
const skill = await skills?.get(invocation.skillName);
|
|
24589
|
+
if (!skill || skill["user-invocable"] === false) {
|
|
24590
|
+
throw new Error(`Skill not found: ${invocation.skillName}.`);
|
|
24591
|
+
}
|
|
24592
|
+
const args = invocation.arguments.trim();
|
|
24593
|
+
const content = `${formatSkillActivation(skill)}${args ? `
|
|
24594
|
+
|
|
24595
|
+
ARGUMENTS: ${args}` : ""}`.trim();
|
|
24596
|
+
return `<skill name="${skill.name}">
|
|
24597
|
+
${escapeSkillBoundary(content)}
|
|
24598
|
+
</skill>`;
|
|
24599
|
+
}
|
|
24600
|
+
async function resolveSourceSession(storage, request) {
|
|
24601
|
+
const session = await storage.sessions.getBySessionId(request.sessionId);
|
|
24602
|
+
if (!session || session.orgId !== request.orgId || session.userId !== request.userId) {
|
|
24603
|
+
throw new Error("Factory session not found");
|
|
24604
|
+
}
|
|
24605
|
+
const projectRepository = await storage.projectRepositories.get({
|
|
24606
|
+
orgId: request.orgId,
|
|
24607
|
+
id: session.projectRepositoryId
|
|
24608
|
+
});
|
|
24609
|
+
if (!projectRepository) throw new Error("Factory session repository not found");
|
|
24610
|
+
const connection = await storage.connections.get({ orgId: request.orgId, id: projectRepository.connectionId });
|
|
24611
|
+
if (!connection || connection.factoryProjectId !== request.factoryProjectId) {
|
|
24612
|
+
throw new Error("Factory session does not belong to this project");
|
|
24613
|
+
}
|
|
24614
|
+
return session;
|
|
24615
|
+
}
|
|
24616
|
+
async function configureThread(session, request) {
|
|
24617
|
+
const threadId = session.thread.requireId();
|
|
24618
|
+
await session.thread.rename({ title: request.threadTitle });
|
|
24619
|
+
const settings = { ...request.threadTags ?? {}, factorySessionId: request.sessionId };
|
|
24620
|
+
await Promise.all(Object.entries(settings).map(([key, value]) => session.thread.setSetting({ key, value })));
|
|
24621
|
+
return threadId;
|
|
24622
|
+
}
|
|
24623
|
+
async function applyMemorySettings(session, record) {
|
|
24624
|
+
if (record?.observerModelId) await session.om.observer.switchModel({ modelId: record.observerModelId });
|
|
24625
|
+
if (record?.reflectorModelId) await session.om.reflector.switchModel({ modelId: record.reflectorModelId });
|
|
24626
|
+
const state = {
|
|
24627
|
+
...record?.observationThreshold != null ? { observationThreshold: record.observationThreshold } : {},
|
|
24628
|
+
...record?.reflectionThreshold != null ? { reflectionThreshold: record.reflectionThreshold } : {},
|
|
24629
|
+
...record?.observeAttachments != null ? { observeAttachments: record.observeAttachments } : {}
|
|
24630
|
+
};
|
|
24631
|
+
if (Object.keys(state).length > 0) await session.state.set(state);
|
|
24632
|
+
}
|
|
24633
|
+
var FactoryStartCoordinator = class {
|
|
24634
|
+
#controller;
|
|
24635
|
+
#storage;
|
|
24636
|
+
#transitionService;
|
|
24637
|
+
#sourceControl;
|
|
24638
|
+
#memorySettings;
|
|
24639
|
+
constructor(controller, storage, transitionService, sourceControl, memorySettings) {
|
|
24640
|
+
this.#controller = controller;
|
|
24641
|
+
this.#storage = storage;
|
|
24642
|
+
this.#transitionService = transitionService;
|
|
24643
|
+
this.#sourceControl = sourceControl;
|
|
24644
|
+
this.#memorySettings = memorySettings;
|
|
24645
|
+
}
|
|
24646
|
+
async prepare(request) {
|
|
24647
|
+
const storage = this.#storage;
|
|
24648
|
+
if (!this.#sourceControl) throw new Error("Factory source control storage is unavailable");
|
|
24649
|
+
const sourceSession = await resolveSourceSession(this.#sourceControl, request);
|
|
24650
|
+
const requestContext = request.requestContext ?? new RequestContext();
|
|
24651
|
+
if (!request.requestContext) {
|
|
24652
|
+
requestContext.set("user", { workosId: request.userId, organizationId: request.orgId });
|
|
24653
|
+
}
|
|
24654
|
+
const sessionState = {
|
|
24655
|
+
factoryProjectId: request.factoryProjectId,
|
|
24656
|
+
projectRepositoryId: sourceSession.projectRepositoryId
|
|
24657
|
+
};
|
|
24658
|
+
const session = await this.#controller.createSession({
|
|
24659
|
+
id: sourceSession.sessionId,
|
|
24660
|
+
ownerId: request.userId,
|
|
24661
|
+
resourceId: sourceSession.sessionId,
|
|
24662
|
+
threadId: sourceSession.sessionId,
|
|
24663
|
+
requestContext,
|
|
24664
|
+
tags: sessionState
|
|
24665
|
+
});
|
|
24666
|
+
await session.state.set(sessionState);
|
|
24667
|
+
if (this.#memorySettings) {
|
|
24668
|
+
try {
|
|
24669
|
+
const record = await this.#memorySettings.get({ orgId: request.orgId, userId: request.userId });
|
|
24670
|
+
await applyMemorySettings(session, record);
|
|
24671
|
+
} catch (error) {
|
|
24672
|
+
console.warn("[Factory Start] Failed to apply observational-memory settings", {
|
|
24673
|
+
error: error instanceof Error ? error.message : String(error)
|
|
24674
|
+
});
|
|
24675
|
+
}
|
|
24676
|
+
}
|
|
24677
|
+
if (request.defaultModelId) {
|
|
24678
|
+
try {
|
|
24679
|
+
await session.model.switch({ modelId: request.defaultModelId });
|
|
24680
|
+
} catch (error) {
|
|
24681
|
+
console.warn("[Factory Start] Failed to apply factory default model", {
|
|
24682
|
+
modelId: request.defaultModelId,
|
|
24683
|
+
error: error instanceof Error ? error.message : String(error)
|
|
24684
|
+
});
|
|
24685
|
+
}
|
|
24686
|
+
}
|
|
24687
|
+
const threadId = await configureThread(session, request);
|
|
24688
|
+
const kickoffMessage = await resolveKickoffMessage(session, request.invocation);
|
|
24689
|
+
const prepared = await storage.prepareRunStart({
|
|
24690
|
+
orgId: request.orgId,
|
|
24691
|
+
userId: request.userId,
|
|
24692
|
+
factoryProjectId: request.factoryProjectId,
|
|
24693
|
+
workItem: { id: request.workItem.id, input: request.workItem.input },
|
|
24694
|
+
role: request.workItem.role,
|
|
24695
|
+
session: { sessionId: sourceSession.sessionId, branch: sourceSession.branch, threadId },
|
|
24696
|
+
resourceId: sourceSession.sessionId,
|
|
24697
|
+
kickoffKey: request.kickoffKey,
|
|
24698
|
+
kickoffMessage
|
|
24699
|
+
});
|
|
24700
|
+
await session.thread.setSetting({ key: "factoryWorkItemId", value: prepared.item.id });
|
|
24701
|
+
let revision = prepared.item.revision;
|
|
24702
|
+
if (prepared.item.stages.length !== 1 || prepared.item.stages[0] !== request.destinationStage) {
|
|
24703
|
+
if (!this.#transitionService) throw new Error("Factory transition service is unavailable.");
|
|
24704
|
+
const transition = await this.#transitionService.transition({
|
|
24705
|
+
orgId: request.orgId,
|
|
24706
|
+
factoryProjectId: request.factoryProjectId,
|
|
24707
|
+
workItemId: prepared.item.id,
|
|
24708
|
+
board: prepared.item.externalSource?.type === "pull-request" ? "review" : "work",
|
|
24709
|
+
stage: request.destinationStage,
|
|
24710
|
+
expectedRevision: prepared.item.revision,
|
|
24711
|
+
actor: { type: "human", id: request.userId },
|
|
24712
|
+
ingress: { type: "human", identity: `start:${request.kickoffKey}:transition` },
|
|
24713
|
+
cause: "run_start"
|
|
24714
|
+
});
|
|
24715
|
+
if (transition.status === "rejected") {
|
|
24716
|
+
await storage.markPendingStart(prepared.binding.id, "failed", transition.reason);
|
|
24717
|
+
throw new FactoryStartTransitionError(transition);
|
|
24718
|
+
}
|
|
24719
|
+
revision = transition.revision;
|
|
24720
|
+
}
|
|
24721
|
+
if (kickoffMessage === null) {
|
|
24722
|
+
await storage.markPendingStart(prepared.binding.id, "sent");
|
|
24723
|
+
prepared.pendingStart.status = "sent";
|
|
24724
|
+
}
|
|
24725
|
+
return {
|
|
24726
|
+
workItemId: prepared.item.id,
|
|
24727
|
+
bindingId: prepared.binding.id,
|
|
24728
|
+
threadId,
|
|
24729
|
+
resourceId: sourceSession.sessionId,
|
|
24730
|
+
sessionId: sourceSession.sessionId,
|
|
24731
|
+
branch: sourceSession.branch,
|
|
24732
|
+
revision,
|
|
24733
|
+
kickoffStatus: prepared.pendingStart.status,
|
|
24734
|
+
replayed: prepared.replayed
|
|
24735
|
+
};
|
|
24736
|
+
}
|
|
24737
|
+
};
|
|
24738
|
+
|
|
24739
|
+
// src/rules/transition-service.ts
|
|
24740
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
24741
|
+
|
|
24602
24742
|
// src/rules/resolve.ts
|
|
24603
24743
|
function resolveFactoryStageRules(rules, input) {
|
|
24604
24744
|
if (input.fromStage === input.toStage && !input.initialEntry) return [];
|
|
@@ -24610,12 +24750,6 @@ function resolveFactoryStageRules(rules, input) {
|
|
|
24610
24750
|
if (onEnter) resolved.push({ phase: "enter", handler: onEnter });
|
|
24611
24751
|
return resolved;
|
|
24612
24752
|
}
|
|
24613
|
-
function resolveFactoryGithubRule(rules, event) {
|
|
24614
|
-
return rules.github[event]?.onEvent;
|
|
24615
|
-
}
|
|
24616
|
-
function resolveFactoryLinearRule(rules, event) {
|
|
24617
|
-
return rules.linear[event]?.onEvent;
|
|
24618
|
-
}
|
|
24619
24753
|
|
|
24620
24754
|
// src/rules/types.ts
|
|
24621
24755
|
var FACTORY_RULE_STAGES = ["intake", "triage", "planning", "execute", "review", "done", "canceled"];
|
|
@@ -24869,508 +25003,8 @@ function validateFactoryRuleDecisions(values, causalDepth = 0) {
|
|
|
24869
25003
|
return decisions;
|
|
24870
25004
|
}
|
|
24871
25005
|
|
|
24872
|
-
// src/rules/github-service.ts
|
|
24873
|
-
var TRUSTED_PERMISSIONS = /* @__PURE__ */ new Set(["write", "admin"]);
|
|
24874
|
-
var RULE_TIMEOUT_MS = 5e3;
|
|
24875
|
-
async function withRuleTimeout(promise) {
|
|
24876
|
-
let timeout;
|
|
24877
|
-
try {
|
|
24878
|
-
return await Promise.race([
|
|
24879
|
-
promise,
|
|
24880
|
-
new Promise((_, reject) => {
|
|
24881
|
-
timeout = setTimeout(() => reject(new Error("FACTORY_RULE_TIMEOUT")), RULE_TIMEOUT_MS);
|
|
24882
|
-
})
|
|
24883
|
-
]);
|
|
24884
|
-
} finally {
|
|
24885
|
-
if (timeout) clearTimeout(timeout);
|
|
24886
|
-
}
|
|
24887
|
-
}
|
|
24888
|
-
function object(value) {
|
|
24889
|
-
return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
|
|
24890
|
-
}
|
|
24891
|
-
function string(value) {
|
|
24892
|
-
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
24893
|
-
}
|
|
24894
|
-
function number(value) {
|
|
24895
|
-
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
24896
|
-
}
|
|
24897
|
-
function boolean(value) {
|
|
24898
|
-
return typeof value === "boolean" ? value : void 0;
|
|
24899
|
-
}
|
|
24900
|
-
function eventName(parsed) {
|
|
24901
|
-
const action = string(parsed.payload.action);
|
|
24902
|
-
if (parsed.event === "issues" && action === "opened") return "issueOpened";
|
|
24903
|
-
if (parsed.event === "pull_request" && action === "opened") return "pullRequestOpened";
|
|
24904
|
-
if (parsed.event === "pull_request" && action === "synchronize") return "pullRequestUpdated";
|
|
24905
|
-
if (parsed.event === "pull_request" && action === "closed" && boolean(object(parsed.payload.pull_request)?.merged)) {
|
|
24906
|
-
return "pullRequestMerged";
|
|
24907
|
-
}
|
|
24908
|
-
if (parsed.event === "pull_request" && action === "review_requested") return "pullRequestReviewRequested";
|
|
24909
|
-
return void 0;
|
|
24910
|
-
}
|
|
24911
|
-
function canonicalSourceKey(kind, itemNumber) {
|
|
24912
|
-
return kind === "issue" ? `github-issue:${itemNumber}` : `github-pr:${itemNumber}`;
|
|
24913
|
-
}
|
|
24914
|
-
function legacySourceKey(repositoryId, kind, itemNumber) {
|
|
24915
|
-
return `github:${repositoryId}:${kind}:${itemNumber}`;
|
|
24916
|
-
}
|
|
24917
|
-
function provenanceTarget(repositoryId, pullRequestNumber) {
|
|
24918
|
-
return `factory-pr-provenance:${repositoryId}:${pullRequestNumber}`;
|
|
24919
|
-
}
|
|
24920
|
-
function workItemSource(item) {
|
|
24921
|
-
if (!item.externalSource) return "manual";
|
|
24922
|
-
return item.externalSource.type === "pull-request" ? "github-pr" : "github-issue";
|
|
24923
|
-
}
|
|
24924
|
-
function workItemSourceKey(item) {
|
|
24925
|
-
return item.externalSource?.externalId ?? null;
|
|
24926
|
-
}
|
|
24927
|
-
async function githubActor(github, input) {
|
|
24928
|
-
let trusted = false;
|
|
24929
|
-
try {
|
|
24930
|
-
const permission = await github.getRepositoryCollaboratorPermission(
|
|
24931
|
-
input.installationId,
|
|
24932
|
-
input.repository,
|
|
24933
|
-
input.login
|
|
24934
|
-
);
|
|
24935
|
-
trusted = permission !== void 0 && TRUSTED_PERMISSIONS.has(permission);
|
|
24936
|
-
} catch {
|
|
24937
|
-
trusted = false;
|
|
24938
|
-
}
|
|
24939
|
-
return { type: "github", login: input.login, trusted, factoryAuthored: input.factoryAuthored };
|
|
24940
|
-
}
|
|
24941
|
-
var FactoryGithubEventService = class {
|
|
24942
|
-
constructor(options) {
|
|
24943
|
-
this.options = options;
|
|
24944
|
-
}
|
|
24945
|
-
options;
|
|
24946
|
-
async ingest(parsed) {
|
|
24947
|
-
const event = eventName(parsed);
|
|
24948
|
-
const repository = object(parsed.payload.repository);
|
|
24949
|
-
const installationId = number(object(parsed.payload.installation)?.id);
|
|
24950
|
-
const repositoryId = number(repository?.id);
|
|
24951
|
-
const repositoryName = string(repository?.full_name);
|
|
24952
|
-
const login = string(object(parsed.payload.sender)?.login);
|
|
24953
|
-
if (!event || !installationId || !repositoryId || !repositoryName || !login) return { status: "ignored" };
|
|
24954
|
-
const projects = await this.options.sourceControl.projectRepositories.listByExternalRepository({
|
|
24955
|
-
installationExternalId: String(installationId),
|
|
24956
|
-
repositoryExternalId: String(repositoryId)
|
|
24957
|
-
});
|
|
24958
|
-
if (projects.length === 0) return { status: "ignored" };
|
|
24959
|
-
const results = [];
|
|
24960
|
-
for (const project of projects) {
|
|
24961
|
-
results.push(
|
|
24962
|
-
await this.#ingestProject(parsed, event, installationId, repositoryId, repositoryName, login, project)
|
|
24963
|
-
);
|
|
24964
|
-
}
|
|
24965
|
-
if (results.some((result) => result.status === "committed")) return { status: "committed" };
|
|
24966
|
-
if (results.some((result) => result.status === "replayed")) return { status: "replayed" };
|
|
24967
|
-
return results[0] ?? { status: "ignored" };
|
|
24968
|
-
}
|
|
24969
|
-
async #ingestProject(parsed, event, installationId, repositoryId, repositoryName, login, project) {
|
|
24970
|
-
const factoryProject = await this.options.projects.get({
|
|
24971
|
-
orgId: project.orgId,
|
|
24972
|
-
id: project.factoryProjectId
|
|
24973
|
-
});
|
|
24974
|
-
if (!factoryProject) return { status: "missing" };
|
|
24975
|
-
const issue = object(parsed.payload.issue);
|
|
24976
|
-
const pullRequest = object(parsed.payload.pull_request);
|
|
24977
|
-
const issueNumber = number(issue?.number);
|
|
24978
|
-
const pullRequestNumber = number(pullRequest?.number);
|
|
24979
|
-
const provenance = pullRequestNumber ? (await this.options.integrationStorage.subscriptions.listByTarget(
|
|
24980
|
-
provenanceTarget(repositoryId, pullRequestNumber),
|
|
24981
|
-
{ status: "active" }
|
|
24982
|
-
)).find((subscription) => subscription.orgId === project.orgId)?.data ?? null : null;
|
|
24983
|
-
const relatedItem = await this.#relatedItem(
|
|
24984
|
-
project.orgId,
|
|
24985
|
-
project.factoryProjectId,
|
|
24986
|
-
repositoryId,
|
|
24987
|
-
issueNumber,
|
|
24988
|
-
pullRequestNumber,
|
|
24989
|
-
string(object(pullRequest?.head)?.ref),
|
|
24990
|
-
provenance
|
|
24991
|
-
);
|
|
24992
|
-
const actor = await githubActor(this.options.github, {
|
|
24993
|
-
installationId,
|
|
24994
|
-
repository: repositoryName,
|
|
24995
|
-
login,
|
|
24996
|
-
factoryAuthored: provenance !== null
|
|
24997
|
-
});
|
|
24998
|
-
const context = {
|
|
24999
|
-
tenant: { orgId: project.orgId, projectId: project.factoryProjectId },
|
|
25000
|
-
actor,
|
|
25001
|
-
ingress: { type: "github", id: `${installationId}:${parsed.deliveryId}` },
|
|
25002
|
-
cause: `github.${event}`,
|
|
25003
|
-
causalChain: [],
|
|
25004
|
-
ruleSetVersion: this.options.rules.version,
|
|
25005
|
-
...relatedItem ? {
|
|
25006
|
-
item: {
|
|
25007
|
-
id: relatedItem.id,
|
|
25008
|
-
source: workItemSource(relatedItem),
|
|
25009
|
-
sourceKey: workItemSourceKey(relatedItem),
|
|
25010
|
-
parentWorkItemId: relatedItem.parentWorkItemId,
|
|
25011
|
-
title: relatedItem.title,
|
|
25012
|
-
url: relatedItem.externalSource?.url ?? null,
|
|
25013
|
-
stages: relatedItem.stages
|
|
25014
|
-
},
|
|
25015
|
-
board: relatedItem.externalSource?.type === "pull-request" ? "review" : "work",
|
|
25016
|
-
itemRevision: relatedItem.revision
|
|
25017
|
-
} : {},
|
|
25018
|
-
event,
|
|
25019
|
-
deliveryId: parsed.deliveryId,
|
|
25020
|
-
factory: { createdAt: factoryProject.createdAt.toISOString() },
|
|
25021
|
-
repository: { id: repositoryId, fullName: repositoryName },
|
|
25022
|
-
...issueNumber && string(issue?.title) && string(issue?.html_url) ? {
|
|
25023
|
-
issue: {
|
|
25024
|
-
number: issueNumber,
|
|
25025
|
-
title: string(issue?.title),
|
|
25026
|
-
url: string(issue?.html_url),
|
|
25027
|
-
...string(issue?.created_at) ? { createdAt: string(issue?.created_at) } : {}
|
|
25028
|
-
}
|
|
25029
|
-
} : {},
|
|
25030
|
-
...pullRequestNumber && string(pullRequest?.title) && string(pullRequest?.html_url) ? {
|
|
25031
|
-
pullRequest: {
|
|
25032
|
-
number: pullRequestNumber,
|
|
25033
|
-
title: string(pullRequest?.title),
|
|
25034
|
-
url: string(pullRequest?.html_url),
|
|
25035
|
-
...string(pullRequest?.created_at) ? { createdAt: string(pullRequest?.created_at) } : {},
|
|
25036
|
-
state: string(pullRequest?.state) === "closed" ? "closed" : "open",
|
|
25037
|
-
merged: boolean(pullRequest?.merged) ?? false,
|
|
25038
|
-
headBranch: string(object(pullRequest?.head)?.ref) ?? "",
|
|
25039
|
-
baseBranch: string(object(pullRequest?.base)?.ref) ?? ""
|
|
25040
|
-
}
|
|
25041
|
-
} : {},
|
|
25042
|
-
...object(parsed.payload.review) ? {
|
|
25043
|
-
review: {
|
|
25044
|
-
id: number(object(parsed.payload.review)?.id) ?? 0,
|
|
25045
|
-
state: string(object(parsed.payload.review)?.state) ?? "unknown",
|
|
25046
|
-
url: string(object(parsed.payload.review)?.html_url) ?? ""
|
|
25047
|
-
}
|
|
25048
|
-
} : {}
|
|
25049
|
-
};
|
|
25050
|
-
const rule = resolveFactoryGithubRule(this.options.rules, event);
|
|
25051
|
-
let decision;
|
|
25052
|
-
let decisions = [];
|
|
25053
|
-
let outcome = { status: "accepted" };
|
|
25054
|
-
try {
|
|
25055
|
-
decision = rule ? await withRuleTimeout(Promise.resolve(rule(Object.freeze(context)))) : void 0;
|
|
25056
|
-
if (decision?.type === "reject") {
|
|
25057
|
-
outcome = { status: "rejected", code: decision.code, reason: decision.reason };
|
|
25058
|
-
} else if (decision) {
|
|
25059
|
-
decisions = validateFactoryRuleDecisions([decision]).map((entry) => ({ ...entry }));
|
|
25060
|
-
}
|
|
25061
|
-
} catch (error) {
|
|
25062
|
-
const timedOut = error instanceof Error && error.message === "FACTORY_RULE_TIMEOUT";
|
|
25063
|
-
outcome = {
|
|
25064
|
-
status: "rejected",
|
|
25065
|
-
code: timedOut ? "timeout" : "rule_error",
|
|
25066
|
-
reason: timedOut ? "Factory rule evaluation timed out." : error instanceof Error ? error.message.slice(0, 2e3) : "Factory GitHub rule failed."
|
|
25067
|
-
};
|
|
25068
|
-
}
|
|
25069
|
-
const committed = await this.options.storage.commitRuleEvaluation({
|
|
25070
|
-
orgId: project.orgId,
|
|
25071
|
-
factoryProjectId: project.factoryProjectId,
|
|
25072
|
-
workItemId: relatedItem?.id ?? null,
|
|
25073
|
-
ingress: { identity: `${installationId}:${parsed.deliveryId}`, triggerType: `github.${event}` },
|
|
25074
|
-
ruleSetVersion: this.options.rules.version,
|
|
25075
|
-
expectedRevision: relatedItem?.revision ?? null,
|
|
25076
|
-
actor: { ...actor },
|
|
25077
|
-
outcome,
|
|
25078
|
-
decisions,
|
|
25079
|
-
causalChain: [],
|
|
25080
|
-
now: /* @__PURE__ */ new Date()
|
|
25081
|
-
});
|
|
25082
|
-
return { status: committed.status };
|
|
25083
|
-
}
|
|
25084
|
-
async #relatedItem(orgId, projectId, repositoryId, issueNumber, pullRequestNumber, pullRequestHeadBranch, provenance) {
|
|
25085
|
-
const items = await this.options.storage.list({ orgId, factoryProjectId: projectId });
|
|
25086
|
-
if (provenance) return items.find((item) => item.id === provenance.workItemId);
|
|
25087
|
-
if (issueNumber) {
|
|
25088
|
-
return items.find((item) => item.externalSource?.externalId === canonicalSourceKey("issue", issueNumber)) ?? items.find((item) => item.externalSource?.externalId === legacySourceKey(repositoryId, "issue", issueNumber));
|
|
25089
|
-
}
|
|
25090
|
-
if (pullRequestNumber) {
|
|
25091
|
-
return items.find((item) => item.externalSource?.externalId === canonicalSourceKey("pull-request", pullRequestNumber)) ?? items.find(
|
|
25092
|
-
(item) => item.externalSource?.externalId === legacySourceKey(repositoryId, "pull-request", pullRequestNumber)
|
|
25093
|
-
) ?? // Provenance fallback: a PR pushed from a work item's session branch
|
|
25094
|
-
// belongs to that item even when no gh-pr-create provenance was
|
|
25095
|
-
// recorded (session predating state seeding, or the PR was opened
|
|
25096
|
-
// outside the tracked tool call). Session branches are per-item
|
|
25097
|
-
// (`factory/issue-N`), so a head-branch match is unambiguous.
|
|
25098
|
-
(pullRequestHeadBranch ? items.find(
|
|
25099
|
-
(item) => item.externalSource?.type !== "pull-request" && Object.values(item.sessions).some((session) => session.branch === pullRequestHeadBranch)
|
|
25100
|
-
) : void 0);
|
|
25101
|
-
}
|
|
25102
|
-
return void 0;
|
|
25103
|
-
}
|
|
25104
|
-
};
|
|
25105
|
-
|
|
25106
|
-
// src/rules/linear-service.ts
|
|
25107
|
-
var RULE_TIMEOUT_MS2 = 5e3;
|
|
25108
|
-
async function withRuleTimeout2(promise) {
|
|
25109
|
-
let timeout;
|
|
25110
|
-
try {
|
|
25111
|
-
return await Promise.race([
|
|
25112
|
-
promise,
|
|
25113
|
-
new Promise((_, reject) => {
|
|
25114
|
-
timeout = setTimeout(() => reject(new Error("FACTORY_RULE_TIMEOUT")), RULE_TIMEOUT_MS2);
|
|
25115
|
-
})
|
|
25116
|
-
]);
|
|
25117
|
-
} finally {
|
|
25118
|
-
if (timeout) clearTimeout(timeout);
|
|
25119
|
-
}
|
|
25120
|
-
}
|
|
25121
|
-
var FactoryLinearIssueService = class {
|
|
25122
|
-
constructor(options) {
|
|
25123
|
-
this.options = options;
|
|
25124
|
-
}
|
|
25125
|
-
options;
|
|
25126
|
-
async ingest(input) {
|
|
25127
|
-
const project = await this.options.projects.get({ orgId: input.orgId, id: input.factoryProjectId });
|
|
25128
|
-
if (!project) return { status: "missing", ingested: 0 };
|
|
25129
|
-
const items = await this.options.storage.list({ orgId: input.orgId, factoryProjectId: input.factoryProjectId });
|
|
25130
|
-
const itemsBySourceKey = new Map(items.map((item) => [item.externalSource?.externalId, item]));
|
|
25131
|
-
const statuses = [];
|
|
25132
|
-
for (const issue of input.issues) {
|
|
25133
|
-
statuses.push(await this.#ingestIssue(input, issue, itemsBySourceKey.get(`linear:${issue.identifier}`)));
|
|
25134
|
-
}
|
|
25135
|
-
if (statuses.some((status) => status === "committed")) return { status: "committed", ingested: statuses.length };
|
|
25136
|
-
if (statuses.some((status) => status === "replayed")) return { status: "replayed", ingested: statuses.length };
|
|
25137
|
-
return { status: "missing", ingested: statuses.length };
|
|
25138
|
-
}
|
|
25139
|
-
async #ingestIssue(input, issue, relatedItem) {
|
|
25140
|
-
const ingressId = `linear:${issue.id}:${issue.updatedAt}`;
|
|
25141
|
-
const actor = { type: "human", id: input.userId };
|
|
25142
|
-
const context = {
|
|
25143
|
-
tenant: { orgId: input.orgId, projectId: input.factoryProjectId },
|
|
25144
|
-
actor,
|
|
25145
|
-
ingress: { type: "linear", id: ingressId },
|
|
25146
|
-
cause: "linear.issueObserved",
|
|
25147
|
-
causalChain: [],
|
|
25148
|
-
ruleSetVersion: this.options.rules.version,
|
|
25149
|
-
...relatedItem ? {
|
|
25150
|
-
item: {
|
|
25151
|
-
id: relatedItem.id,
|
|
25152
|
-
source: "linear-issue",
|
|
25153
|
-
sourceKey: relatedItem.externalSource?.externalId ?? null,
|
|
25154
|
-
parentWorkItemId: relatedItem.parentWorkItemId,
|
|
25155
|
-
title: relatedItem.title,
|
|
25156
|
-
url: relatedItem.externalSource?.url ?? null,
|
|
25157
|
-
stages: relatedItem.stages
|
|
25158
|
-
},
|
|
25159
|
-
board: "work",
|
|
25160
|
-
itemRevision: relatedItem.revision
|
|
25161
|
-
} : {},
|
|
25162
|
-
event: "issueObserved",
|
|
25163
|
-
issue
|
|
25164
|
-
};
|
|
25165
|
-
const rule = resolveFactoryLinearRule(this.options.rules, context.event);
|
|
25166
|
-
let decision;
|
|
25167
|
-
let decisions = [];
|
|
25168
|
-
let outcome = { status: "accepted" };
|
|
25169
|
-
try {
|
|
25170
|
-
decision = rule ? await withRuleTimeout2(Promise.resolve(rule(Object.freeze(context)))) : void 0;
|
|
25171
|
-
if (decision?.type === "reject") {
|
|
25172
|
-
outcome = { status: "rejected", code: decision.code, reason: decision.reason };
|
|
25173
|
-
} else if (decision) {
|
|
25174
|
-
decisions = validateFactoryRuleDecisions([decision]).map((entry) => ({ ...entry }));
|
|
25175
|
-
}
|
|
25176
|
-
} catch (error) {
|
|
25177
|
-
const timedOut = error instanceof Error && error.message === "FACTORY_RULE_TIMEOUT";
|
|
25178
|
-
outcome = {
|
|
25179
|
-
status: "rejected",
|
|
25180
|
-
code: timedOut ? "timeout" : "rule_error",
|
|
25181
|
-
reason: timedOut ? "Factory rule evaluation timed out." : error instanceof Error ? error.message.slice(0, 2e3) : "Factory Linear rule failed."
|
|
25182
|
-
};
|
|
25183
|
-
}
|
|
25184
|
-
const committed = await this.options.storage.commitRuleEvaluation({
|
|
25185
|
-
orgId: input.orgId,
|
|
25186
|
-
factoryProjectId: input.factoryProjectId,
|
|
25187
|
-
workItemId: relatedItem?.id ?? null,
|
|
25188
|
-
ingress: { identity: ingressId, triggerType: "linear.issueObserved" },
|
|
25189
|
-
ruleSetVersion: this.options.rules.version,
|
|
25190
|
-
expectedRevision: relatedItem?.revision ?? null,
|
|
25191
|
-
actor,
|
|
25192
|
-
outcome,
|
|
25193
|
-
decisions,
|
|
25194
|
-
causalChain: [],
|
|
25195
|
-
now: /* @__PURE__ */ new Date()
|
|
25196
|
-
});
|
|
25197
|
-
return committed.status;
|
|
25198
|
-
}
|
|
25199
|
-
};
|
|
25200
|
-
|
|
25201
|
-
// src/rules/start-coordinator.ts
|
|
25202
|
-
import { RequestContext } from "@mastra/core/request-context";
|
|
25203
|
-
import { formatSkillActivation } from "@mastra/core/workspace";
|
|
25204
|
-
var FactoryStartTransitionError = class extends Error {
|
|
25205
|
-
result;
|
|
25206
|
-
constructor(result) {
|
|
25207
|
-
super(result.reason);
|
|
25208
|
-
this.name = "FactoryStartTransitionError";
|
|
25209
|
-
this.result = result;
|
|
25210
|
-
}
|
|
25211
|
-
};
|
|
25212
|
-
function escapeSkillBoundary(value) {
|
|
25213
|
-
return value.replaceAll("</skill>", "</skill>");
|
|
25214
|
-
}
|
|
25215
|
-
async function resolveKickoffMessage(session, invocation) {
|
|
25216
|
-
if (!invocation) return null;
|
|
25217
|
-
if (invocation.type === "prompt") return invocation.prompt;
|
|
25218
|
-
const skills = session.getWorkspace().skills;
|
|
25219
|
-
await skills?.maybeRefresh();
|
|
25220
|
-
const skill = await skills?.get(invocation.skillName);
|
|
25221
|
-
if (!skill || skill["user-invocable"] === false) {
|
|
25222
|
-
throw new Error(`Skill not found: ${invocation.skillName}.`);
|
|
25223
|
-
}
|
|
25224
|
-
const args = invocation.arguments.trim();
|
|
25225
|
-
const content = `${formatSkillActivation(skill)}${args ? `
|
|
25226
|
-
|
|
25227
|
-
ARGUMENTS: ${args}` : ""}`.trim();
|
|
25228
|
-
return `<skill name="${skill.name}">
|
|
25229
|
-
${escapeSkillBoundary(content)}
|
|
25230
|
-
</skill>`;
|
|
25231
|
-
}
|
|
25232
|
-
async function resolveSourceSession(storage, request) {
|
|
25233
|
-
const session = await storage.sessions.getBySessionId(request.sessionId);
|
|
25234
|
-
if (!session || session.orgId !== request.orgId || session.userId !== request.userId) {
|
|
25235
|
-
throw new Error("Factory session not found");
|
|
25236
|
-
}
|
|
25237
|
-
const projectRepository = await storage.projectRepositories.get({
|
|
25238
|
-
orgId: request.orgId,
|
|
25239
|
-
id: session.projectRepositoryId
|
|
25240
|
-
});
|
|
25241
|
-
if (!projectRepository) throw new Error("Factory session repository not found");
|
|
25242
|
-
const connection = await storage.connections.get({ orgId: request.orgId, id: projectRepository.connectionId });
|
|
25243
|
-
if (!connection || connection.factoryProjectId !== request.factoryProjectId) {
|
|
25244
|
-
throw new Error("Factory session does not belong to this project");
|
|
25245
|
-
}
|
|
25246
|
-
return session;
|
|
25247
|
-
}
|
|
25248
|
-
async function configureThread(session, request) {
|
|
25249
|
-
const threadId = session.thread.requireId();
|
|
25250
|
-
await session.thread.rename({ title: request.threadTitle });
|
|
25251
|
-
const settings = { ...request.threadTags ?? {}, factorySessionId: request.sessionId };
|
|
25252
|
-
await Promise.all(Object.entries(settings).map(([key, value]) => session.thread.setSetting({ key, value })));
|
|
25253
|
-
return threadId;
|
|
25254
|
-
}
|
|
25255
|
-
async function applyMemorySettings(session, record) {
|
|
25256
|
-
if (record?.observerModelId) await session.om.observer.switchModel({ modelId: record.observerModelId });
|
|
25257
|
-
if (record?.reflectorModelId) await session.om.reflector.switchModel({ modelId: record.reflectorModelId });
|
|
25258
|
-
const state = {
|
|
25259
|
-
...record?.observationThreshold != null ? { observationThreshold: record.observationThreshold } : {},
|
|
25260
|
-
...record?.reflectionThreshold != null ? { reflectionThreshold: record.reflectionThreshold } : {},
|
|
25261
|
-
...record?.observeAttachments != null ? { observeAttachments: record.observeAttachments } : {}
|
|
25262
|
-
};
|
|
25263
|
-
if (Object.keys(state).length > 0) await session.state.set(state);
|
|
25264
|
-
}
|
|
25265
|
-
var FactoryStartCoordinator = class {
|
|
25266
|
-
#controller;
|
|
25267
|
-
#storage;
|
|
25268
|
-
#transitionService;
|
|
25269
|
-
#sourceControl;
|
|
25270
|
-
#memorySettings;
|
|
25271
|
-
constructor(controller, storage, transitionService, sourceControl, memorySettings) {
|
|
25272
|
-
this.#controller = controller;
|
|
25273
|
-
this.#storage = storage;
|
|
25274
|
-
this.#transitionService = transitionService;
|
|
25275
|
-
this.#sourceControl = sourceControl;
|
|
25276
|
-
this.#memorySettings = memorySettings;
|
|
25277
|
-
}
|
|
25278
|
-
async prepare(request) {
|
|
25279
|
-
const storage = this.#storage;
|
|
25280
|
-
if (!this.#sourceControl) throw new Error("Factory source control storage is unavailable");
|
|
25281
|
-
const sourceSession = await resolveSourceSession(this.#sourceControl, request);
|
|
25282
|
-
const requestContext = request.requestContext ?? new RequestContext();
|
|
25283
|
-
if (!request.requestContext) {
|
|
25284
|
-
requestContext.set("user", { workosId: request.userId, organizationId: request.orgId });
|
|
25285
|
-
}
|
|
25286
|
-
const sessionState = {
|
|
25287
|
-
factoryProjectId: request.factoryProjectId,
|
|
25288
|
-
projectRepositoryId: sourceSession.projectRepositoryId
|
|
25289
|
-
};
|
|
25290
|
-
const session = await this.#controller.createSession({
|
|
25291
|
-
id: sourceSession.sessionId,
|
|
25292
|
-
ownerId: request.userId,
|
|
25293
|
-
resourceId: sourceSession.sessionId,
|
|
25294
|
-
threadId: sourceSession.sessionId,
|
|
25295
|
-
requestContext,
|
|
25296
|
-
tags: sessionState
|
|
25297
|
-
});
|
|
25298
|
-
await session.state.set(sessionState);
|
|
25299
|
-
if (this.#memorySettings) {
|
|
25300
|
-
try {
|
|
25301
|
-
const record = await this.#memorySettings.get({ orgId: request.orgId, userId: request.userId });
|
|
25302
|
-
await applyMemorySettings(session, record);
|
|
25303
|
-
} catch (error) {
|
|
25304
|
-
console.warn("[Factory Start] Failed to apply observational-memory settings", {
|
|
25305
|
-
error: error instanceof Error ? error.message : String(error)
|
|
25306
|
-
});
|
|
25307
|
-
}
|
|
25308
|
-
}
|
|
25309
|
-
if (request.defaultModelId) {
|
|
25310
|
-
try {
|
|
25311
|
-
await session.model.switch({ modelId: request.defaultModelId });
|
|
25312
|
-
} catch (error) {
|
|
25313
|
-
console.warn("[Factory Start] Failed to apply factory default model", {
|
|
25314
|
-
modelId: request.defaultModelId,
|
|
25315
|
-
error: error instanceof Error ? error.message : String(error)
|
|
25316
|
-
});
|
|
25317
|
-
}
|
|
25318
|
-
}
|
|
25319
|
-
const threadId = await configureThread(session, request);
|
|
25320
|
-
const kickoffMessage = await resolveKickoffMessage(session, request.invocation);
|
|
25321
|
-
const prepared = await storage.prepareRunStart({
|
|
25322
|
-
orgId: request.orgId,
|
|
25323
|
-
userId: request.userId,
|
|
25324
|
-
factoryProjectId: request.factoryProjectId,
|
|
25325
|
-
workItem: { id: request.workItem.id, input: request.workItem.input },
|
|
25326
|
-
role: request.workItem.role,
|
|
25327
|
-
session: { sessionId: sourceSession.sessionId, branch: sourceSession.branch, threadId },
|
|
25328
|
-
resourceId: sourceSession.sessionId,
|
|
25329
|
-
kickoffKey: request.kickoffKey,
|
|
25330
|
-
kickoffMessage
|
|
25331
|
-
});
|
|
25332
|
-
await session.thread.setSetting({ key: "factoryWorkItemId", value: prepared.item.id });
|
|
25333
|
-
let revision = prepared.item.revision;
|
|
25334
|
-
if (prepared.item.stages.length !== 1 || prepared.item.stages[0] !== request.destinationStage) {
|
|
25335
|
-
if (!this.#transitionService) throw new Error("Factory transition service is unavailable.");
|
|
25336
|
-
const transition = await this.#transitionService.transition({
|
|
25337
|
-
orgId: request.orgId,
|
|
25338
|
-
factoryProjectId: request.factoryProjectId,
|
|
25339
|
-
workItemId: prepared.item.id,
|
|
25340
|
-
board: prepared.item.externalSource?.type === "pull-request" ? "review" : "work",
|
|
25341
|
-
stage: request.destinationStage,
|
|
25342
|
-
expectedRevision: prepared.item.revision,
|
|
25343
|
-
actor: { type: "human", id: request.userId },
|
|
25344
|
-
ingress: { type: "human", identity: `start:${request.kickoffKey}:transition` },
|
|
25345
|
-
cause: "run_start"
|
|
25346
|
-
});
|
|
25347
|
-
if (transition.status === "rejected") {
|
|
25348
|
-
await storage.markPendingStart(prepared.binding.id, "failed", transition.reason);
|
|
25349
|
-
throw new FactoryStartTransitionError(transition);
|
|
25350
|
-
}
|
|
25351
|
-
revision = transition.revision;
|
|
25352
|
-
}
|
|
25353
|
-
if (kickoffMessage === null) {
|
|
25354
|
-
await storage.markPendingStart(prepared.binding.id, "sent");
|
|
25355
|
-
prepared.pendingStart.status = "sent";
|
|
25356
|
-
}
|
|
25357
|
-
return {
|
|
25358
|
-
workItemId: prepared.item.id,
|
|
25359
|
-
bindingId: prepared.binding.id,
|
|
25360
|
-
threadId,
|
|
25361
|
-
resourceId: sourceSession.sessionId,
|
|
25362
|
-
sessionId: sourceSession.sessionId,
|
|
25363
|
-
branch: sourceSession.branch,
|
|
25364
|
-
revision,
|
|
25365
|
-
kickoffStatus: prepared.pendingStart.status,
|
|
25366
|
-
replayed: prepared.replayed
|
|
25367
|
-
};
|
|
25368
|
-
}
|
|
25369
|
-
};
|
|
25370
|
-
|
|
25371
25006
|
// src/rules/transition-service.ts
|
|
25372
|
-
|
|
25373
|
-
var RULE_TIMEOUT_MS3 = 5e3;
|
|
25007
|
+
var RULE_TIMEOUT_MS = 5e3;
|
|
25374
25008
|
var MAX_REJECTION_REASON = 512;
|
|
25375
25009
|
function rejection(transitionId, itemId, code, reason) {
|
|
25376
25010
|
return { status: "rejected", transitionId, itemId, code, reason: reason.slice(0, MAX_REJECTION_REASON) };
|
|
@@ -25391,7 +25025,7 @@ function currentStage(stages) {
|
|
|
25391
25025
|
const stage = stages[0];
|
|
25392
25026
|
return FACTORY_RULE_STAGES.includes(stage) ? stage : void 0;
|
|
25393
25027
|
}
|
|
25394
|
-
function
|
|
25028
|
+
function workItemSource(source) {
|
|
25395
25029
|
if (!source) return "manual";
|
|
25396
25030
|
if (source.integrationId === "linear") return "linear-issue";
|
|
25397
25031
|
return source.type === "pull-request" ? "github-pr" : "github-issue";
|
|
@@ -25411,7 +25045,7 @@ function ruleFailure(error) {
|
|
|
25411
25045
|
reason: error instanceof Error ? `Factory rule failed: ${error.message}` : "Factory rule failed."
|
|
25412
25046
|
};
|
|
25413
25047
|
}
|
|
25414
|
-
async function
|
|
25048
|
+
async function withRuleTimeout(operation, timeoutMs) {
|
|
25415
25049
|
let timer;
|
|
25416
25050
|
const timeout = new Promise((_, reject) => {
|
|
25417
25051
|
timer = setTimeout(() => reject(new Error("FACTORY_RULE_TIMEOUT")), timeoutMs);
|
|
@@ -25429,7 +25063,7 @@ var FactoryTransitionService = class {
|
|
|
25429
25063
|
constructor(options) {
|
|
25430
25064
|
this.#rules = options.rules;
|
|
25431
25065
|
this.#storage = options.storage;
|
|
25432
|
-
this.#timeoutMs = options.timeoutMs ??
|
|
25066
|
+
this.#timeoutMs = options.timeoutMs ?? RULE_TIMEOUT_MS;
|
|
25433
25067
|
}
|
|
25434
25068
|
get ruleSetVersion() {
|
|
25435
25069
|
return this.#rules.version;
|
|
@@ -25454,7 +25088,7 @@ var FactoryTransitionService = class {
|
|
|
25454
25088
|
"Factory rule causal depth exceeded."
|
|
25455
25089
|
);
|
|
25456
25090
|
}
|
|
25457
|
-
const itemSource =
|
|
25091
|
+
const itemSource = workItemSource(item.externalSource);
|
|
25458
25092
|
const source = factoryRuleSourceForWorkItem(itemSource);
|
|
25459
25093
|
if (request.board === "review" !== (source === "pullRequest")) {
|
|
25460
25094
|
return this.#commitRejection(
|
|
@@ -25497,7 +25131,7 @@ var FactoryTransitionService = class {
|
|
|
25497
25131
|
};
|
|
25498
25132
|
let evaluation;
|
|
25499
25133
|
try {
|
|
25500
|
-
evaluation = await
|
|
25134
|
+
evaluation = await withRuleTimeout(
|
|
25501
25135
|
(async () => {
|
|
25502
25136
|
const decisions = [];
|
|
25503
25137
|
for (const rule of resolveFactoryStageRules(this.#rules, {
|
|
@@ -28816,6 +28450,7 @@ function buildIntegrationContext(deps, integrationId) {
|
|
|
28816
28450
|
projects: deps.domains.projects,
|
|
28817
28451
|
intake: deps.domains.intake
|
|
28818
28452
|
},
|
|
28453
|
+
...deps.factoryReady ? { rules: { config: deps.rules, workItems: deps.domains.workItems } } : {},
|
|
28819
28454
|
...deps.emitAudit ? { hooks: { emitAudit: deps.emitAudit } } : {}
|
|
28820
28455
|
};
|
|
28821
28456
|
}
|
|
@@ -28866,36 +28501,12 @@ function assembleFactoryApiRoutes(deps) {
|
|
|
28866
28501
|
const emitAudit = (args) => deps.audit.emit(args);
|
|
28867
28502
|
const registrations = deps.integrations ?? [];
|
|
28868
28503
|
const githubRegistration = registrations.find(({ integration }) => integration.id === "github");
|
|
28869
|
-
const linearRegistration = registrations.find(({ integration }) => integration.id === "linear");
|
|
28870
28504
|
const githubStorage = githubRegistration ? deps.sourceControlStorage.forIntegration("github") : void 0;
|
|
28871
28505
|
const githubIntegration = githubRegistration?.integration;
|
|
28872
|
-
const workItems = deps.factoryReady ? deps.domains.workItems : void 0;
|
|
28873
|
-
const githubEventService = githubIntegration && githubStorage && workItems ? new FactoryGithubEventService({
|
|
28874
|
-
github: githubIntegration,
|
|
28875
|
-
sourceControl: githubStorage,
|
|
28876
|
-
integrationStorage: deps.integrationStorage.forIntegration("github"),
|
|
28877
|
-
projects: deps.domains.projects,
|
|
28878
|
-
storage: workItems,
|
|
28879
|
-
rules: deps.rules
|
|
28880
|
-
}) : void 0;
|
|
28881
|
-
const linearIssueService = linearRegistration && workItems ? new FactoryLinearIssueService({
|
|
28882
|
-
projects: deps.domains.projects,
|
|
28883
|
-
storage: workItems,
|
|
28884
|
-
rules: deps.rules
|
|
28885
|
-
}) : void 0;
|
|
28886
28506
|
const integrationRoutes = registrations.flatMap((registration) => {
|
|
28887
28507
|
const { integration } = registration;
|
|
28888
28508
|
if (!deps.stateSigner) return disabledIntegrationStatusRoutes(deps, integration.id, true);
|
|
28889
28509
|
const context = buildIntegrationContext({ ...deps, stateSigner: deps.stateSigner, emitAudit }, integration.id);
|
|
28890
|
-
if (integration.id === "github") {
|
|
28891
|
-
context.hooks = {
|
|
28892
|
-
...context.hooks,
|
|
28893
|
-
...githubEventService ? { ingestGithubEvent: (event) => githubEventService.ingest(event) } : {}
|
|
28894
|
-
};
|
|
28895
|
-
}
|
|
28896
|
-
if (integration.id === "linear" && linearIssueService) {
|
|
28897
|
-
context.hooks = { ...context.hooks, ingestLinearIssues: (input) => linearIssueService.ingest(input) };
|
|
28898
|
-
}
|
|
28899
28510
|
return guardIntegrationRoutes({ ...registration, routes: integration.routes(context) });
|
|
28900
28511
|
});
|
|
28901
28512
|
const absentStubs = ["github", "linear"].filter((id) => !registrations.some(({ integration }) => integration.id === id)).flatMap((id) => disabledIntegrationStatusRoutes(deps, id));
|