@stackbone/cli 0.2.2 → 0.2.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 +6 -0
- package/main.js +501 -211
- package/package.json +1 -1
- package/stackbone-cli-0.2.4.tgz +0 -0
- package/stackbone-cli-0.2.2.tgz +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.2.3] - 2026-07-06
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **`stackbone init` (and every other command) could crash with `ERR_MODULE_NOT_FOUND: Cannot find package 'drizzle-orm'`** on some `pnpm dlx`/global-install layouts. The CLI carried a dead "marker import" of `drizzle-kit/api` purely so the bundler would register `drizzle-kit` as a dependency — but that import is loaded eagerly on every CLI boot, and `drizzle-kit/api` itself requires `drizzle-orm` without declaring it as a dependency. On pnpm setups with an isolated `node_modules` layout, `drizzle-kit` can't see `drizzle-orm` even when it's installed right next to it, so the CLI crashed before running any command. Removed the marker import; `drizzle-kit` is now declared explicitly in the build config instead, and the CLI only touches `drizzle-kit` at all when a migration is genuinely being generated (`db migrate create`, or `stackbone dev`'s auto-migrate).
|
|
15
|
+
|
|
10
16
|
## [0.2.2] - 2026-07-06
|
|
11
17
|
|
|
12
18
|
### Fixed
|
package/main.js
CHANGED
|
@@ -38,7 +38,6 @@ import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
|
|
38
38
|
import { cancel, intro, isCancel, log, note, outro, select, spinner, text as text$1 } from "@clack/prompts";
|
|
39
39
|
import open$1 from "open";
|
|
40
40
|
import { readMigrationFiles } from "drizzle-orm/migrator";
|
|
41
|
-
import "drizzle-kit/api";
|
|
42
41
|
import { createServer } from "node:net";
|
|
43
42
|
import { create } from "tar";
|
|
44
43
|
import { Readable } from "node:stream";
|
|
@@ -2989,7 +2988,7 @@ var DEV_HMAC_SECRET = "dev-stackbone-local-emulator-hmac-secret";
|
|
|
2989
2988
|
//#endregion
|
|
2990
2989
|
//#region ../../libs/runtime/agent-emulator/src/lib/server/contract.ts
|
|
2991
2990
|
init_src$14();
|
|
2992
|
-
var STACKBONE_CLI_BUILD_VERSION = "0.2.
|
|
2991
|
+
var STACKBONE_CLI_BUILD_VERSION = "0.2.4";
|
|
2993
2992
|
/**
|
|
2994
2993
|
* Capabilities the local emulator advertises on `GET /api/contract`, derived
|
|
2995
2994
|
* from the route registry above so the advertised set and the mounted routes
|
|
@@ -3020,7 +3019,11 @@ var buildContractResponse = () => contractResponseSchema.parse({
|
|
|
3020
3019
|
});
|
|
3021
3020
|
//#endregion
|
|
3022
3021
|
//#region ../../libs/runtime/agent-emulator/src/lib/server/cors.ts
|
|
3023
|
-
var DEFAULT_ALLOWED_ORIGINS = [
|
|
3022
|
+
var DEFAULT_ALLOWED_ORIGINS = [
|
|
3023
|
+
"https://app.stackbone.ai",
|
|
3024
|
+
"https://chat.stackbone.ai",
|
|
3025
|
+
"http://localhost:*"
|
|
3026
|
+
];
|
|
3024
3027
|
var escapeRegex = (input) => input.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
|
|
3025
3028
|
var compilePattern = (pattern) => {
|
|
3026
3029
|
const escaped = escapeRegex(pattern.trim()).replace(/\*/g, "[^/.]+");
|
|
@@ -13709,7 +13712,15 @@ var init_trigger_descriptor = __esmMin((() => {
|
|
|
13709
13712
|
/** Dot-path, per item, to the sortable marker used to compute the next cursor. */
|
|
13710
13713
|
field: z.string(),
|
|
13711
13714
|
/** Request arg set to the stored cursor so the provider filters server-side. */
|
|
13712
|
-
param: z.string()
|
|
13715
|
+
param: z.string(),
|
|
13716
|
+
/**
|
|
13717
|
+
* Optional template for the parameter value — when present, the stored cursor
|
|
13718
|
+
* is interpolated into this template via `{cursor}` instead of injected as a
|
|
13719
|
+
* bare value. Use when the provider needs a full expression rather than a raw
|
|
13720
|
+
* value, e.g. `receivedDateTime gt {cursor}` for OData `$filter` params.
|
|
13721
|
+
* Absent = backward-compatible bare-value injection.
|
|
13722
|
+
*/
|
|
13723
|
+
cursorTemplate: z.string().optional()
|
|
13713
13724
|
}), z.object({
|
|
13714
13725
|
kind: z.literal("opaque"),
|
|
13715
13726
|
/** Dot-path in the list response to the next opaque token. */
|
|
@@ -13729,6 +13740,23 @@ var init_trigger_descriptor = __esmMin((() => {
|
|
|
13729
13740
|
pageToken: z.object({
|
|
13730
13741
|
requestParam: z.string(),
|
|
13731
13742
|
responsePath: z.string()
|
|
13743
|
+
}).optional(),
|
|
13744
|
+
/**
|
|
13745
|
+
* Offset-based pagination via `$skip`/`$top` — an alternative to `pageToken`
|
|
13746
|
+
* for providers whose OpenAPI spec does not expose the page cursor (e.g.
|
|
13747
|
+
* Microsoft Graph, which paginates via `@odata.nextLink` URLs but only
|
|
13748
|
+
* exposes `$skip` as a query parameter). When present, the engine calls the
|
|
13749
|
+
* list operation with `pageSizeParam` set to `stride` on every request, and
|
|
13750
|
+
* increments `param` by `stride` each page. Stops when a page returns fewer
|
|
13751
|
+
* items than `stride`. Mutually exclusive with `pageToken`.
|
|
13752
|
+
*/
|
|
13753
|
+
pageSkip: z.object({
|
|
13754
|
+
/** Query param name for the offset, e.g. `$skip`. */
|
|
13755
|
+
param: z.string(),
|
|
13756
|
+
/** Query param name for the page size, e.g. `$top`. */
|
|
13757
|
+
pageSizeParam: z.string(),
|
|
13758
|
+
/** Number of items per page, also the stride for incrementing `param`. */
|
|
13759
|
+
stride: z.number()
|
|
13732
13760
|
}).optional()
|
|
13733
13761
|
});
|
|
13734
13762
|
triggerItemStepSchema = z.object({
|
|
@@ -13897,6 +13925,173 @@ var init_registry_store = __esmMin((() => {
|
|
|
13897
13925
|
};
|
|
13898
13926
|
}));
|
|
13899
13927
|
//#endregion
|
|
13928
|
+
//#region ../../libs/shared/connect-registry/src/lib/catalog/gmail/gmail.connector.ts
|
|
13929
|
+
var GMAIL_CONNECTOR;
|
|
13930
|
+
var init_gmail_connector = __esmMin((() => {
|
|
13931
|
+
GMAIL_CONNECTOR = {
|
|
13932
|
+
id: "gmail",
|
|
13933
|
+
displayName: "Gmail",
|
|
13934
|
+
description: "Send email and read messages from a connected Gmail account.",
|
|
13935
|
+
logoUrl: "https://t0.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://mail.google.com&size=64",
|
|
13936
|
+
category: "email",
|
|
13937
|
+
protocol: "openapi",
|
|
13938
|
+
baseUrl: "https://gmail.googleapis.com/gmail/v1/users/me",
|
|
13939
|
+
authMode: "oauth",
|
|
13940
|
+
placement: { kind: "bearer" },
|
|
13941
|
+
scopes: [
|
|
13942
|
+
"openid",
|
|
13943
|
+
"email",
|
|
13944
|
+
"profile",
|
|
13945
|
+
"https://www.googleapis.com/auth/gmail.readonly",
|
|
13946
|
+
"https://www.googleapis.com/auth/gmail.send"
|
|
13947
|
+
],
|
|
13948
|
+
authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
13949
|
+
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
13950
|
+
authorizeParams: {
|
|
13951
|
+
access_type: "offline",
|
|
13952
|
+
prompt: "consent"
|
|
13953
|
+
},
|
|
13954
|
+
specSource: {
|
|
13955
|
+
kind: "url",
|
|
13956
|
+
url: "https://api.apis.guru/v2/specs/googleapis.com/gmail/v1/openapi.json"
|
|
13957
|
+
},
|
|
13958
|
+
triggers: [{
|
|
13959
|
+
id: "message-received",
|
|
13960
|
+
displayName: "Message received",
|
|
13961
|
+
description: "Fires when a new message arrives in the inbox.",
|
|
13962
|
+
sampleData: {
|
|
13963
|
+
messageId: "18e0a1b2c3d4e5f6",
|
|
13964
|
+
threadId: "18e0a1b2c3d4e5f6",
|
|
13965
|
+
from: "Ada Lovelace <ada@example.com>",
|
|
13966
|
+
to: "agent@stackbone.ai",
|
|
13967
|
+
subject: "Quarterly report",
|
|
13968
|
+
snippet: "Here is the quarterly report you asked for…",
|
|
13969
|
+
date: "Mon, 10 Jun 2024 09:15:00 +0000",
|
|
13970
|
+
raw: {
|
|
13971
|
+
messageId: "18e0a1b2c3d4e5f6",
|
|
13972
|
+
threadId: "18e0a1b2c3d4e5f6",
|
|
13973
|
+
historyId: "987654"
|
|
13974
|
+
}
|
|
13975
|
+
},
|
|
13976
|
+
poll: {
|
|
13977
|
+
kind: "strategy",
|
|
13978
|
+
strategy: "gmail.history"
|
|
13979
|
+
}
|
|
13980
|
+
}]
|
|
13981
|
+
};
|
|
13982
|
+
}));
|
|
13983
|
+
//#endregion
|
|
13984
|
+
//#region ../../libs/shared/connect-registry/src/lib/catalog/outlook/outlook.connector.ts
|
|
13985
|
+
var OUTLOOK_CONNECTOR;
|
|
13986
|
+
var init_outlook_connector = __esmMin((() => {
|
|
13987
|
+
OUTLOOK_CONNECTOR = {
|
|
13988
|
+
id: "outlook",
|
|
13989
|
+
displayName: "Outlook",
|
|
13990
|
+
description: "Send email and read messages from a connected Outlook account.",
|
|
13991
|
+
logoUrl: "https://t0.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://microsoft.com&size=64",
|
|
13992
|
+
category: "email",
|
|
13993
|
+
protocol: "openapi",
|
|
13994
|
+
baseUrl: "https://graph.microsoft.com/v1.0",
|
|
13995
|
+
authMode: "oauth",
|
|
13996
|
+
placement: { kind: "bearer" },
|
|
13997
|
+
scopes: [
|
|
13998
|
+
"openid",
|
|
13999
|
+
"email",
|
|
14000
|
+
"profile",
|
|
14001
|
+
"Mail.Read",
|
|
14002
|
+
"Mail.Send",
|
|
14003
|
+
"offline_access"
|
|
14004
|
+
],
|
|
14005
|
+
authorizeUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
14006
|
+
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
|
14007
|
+
specSource: {
|
|
14008
|
+
kind: "url",
|
|
14009
|
+
url: "https://raw.githubusercontent.com/microsoftgraph/msgraph-metadata/master/openapi/v1.0/default.yaml"
|
|
14010
|
+
},
|
|
14011
|
+
authorizeParams: { prompt: "consent" },
|
|
14012
|
+
triggers: [{
|
|
14013
|
+
id: "message-received",
|
|
14014
|
+
displayName: "Message received",
|
|
14015
|
+
description: "Fires when a new message arrives in the Inbox.",
|
|
14016
|
+
sampleData: {
|
|
14017
|
+
messageId: "AAMkAD...",
|
|
14018
|
+
conversationId: "AAQkAD...",
|
|
14019
|
+
from: {
|
|
14020
|
+
name: "Ada Lovelace",
|
|
14021
|
+
address: "ada@example.com"
|
|
14022
|
+
},
|
|
14023
|
+
subject: "Quarterly report",
|
|
14024
|
+
snippet: "Here is the quarterly report...",
|
|
14025
|
+
date: "2024-06-10T09:15:00Z",
|
|
14026
|
+
isRead: false
|
|
14027
|
+
},
|
|
14028
|
+
poll: {
|
|
14029
|
+
kind: "declarative",
|
|
14030
|
+
list: {
|
|
14031
|
+
operationId: "me.mailFolders.ListMessages",
|
|
14032
|
+
args: { "mailFolder-id": "Inbox" },
|
|
14033
|
+
itemsPath: "value",
|
|
14034
|
+
pageSkip: {
|
|
14035
|
+
param: "$skip",
|
|
14036
|
+
pageSizeParam: "$top",
|
|
14037
|
+
stride: 100
|
|
14038
|
+
}
|
|
14039
|
+
},
|
|
14040
|
+
cursor: {
|
|
14041
|
+
kind: "timestamp",
|
|
14042
|
+
field: "receivedDateTime",
|
|
14043
|
+
param: "$filter",
|
|
14044
|
+
cursorTemplate: "receivedDateTime gt {cursor}"
|
|
14045
|
+
},
|
|
14046
|
+
dedup: { idPath: "id" },
|
|
14047
|
+
map: {
|
|
14048
|
+
messageId: "id",
|
|
14049
|
+
conversationId: "conversationId",
|
|
14050
|
+
from: "from",
|
|
14051
|
+
subject: "subject",
|
|
14052
|
+
snippet: "bodyPreview",
|
|
14053
|
+
date: "receivedDateTime",
|
|
14054
|
+
isRead: "isRead"
|
|
14055
|
+
}
|
|
14056
|
+
}
|
|
14057
|
+
}]
|
|
14058
|
+
};
|
|
14059
|
+
}));
|
|
14060
|
+
//#endregion
|
|
14061
|
+
//#region ../../libs/shared/connect-registry/src/lib/catalog/telegram/telegram.connector.ts
|
|
14062
|
+
var TELEGRAM_CONNECTOR;
|
|
14063
|
+
var init_telegram_connector = __esmMin((() => {
|
|
14064
|
+
TELEGRAM_CONNECTOR = {
|
|
14065
|
+
id: "telegram",
|
|
14066
|
+
displayName: "Telegram",
|
|
14067
|
+
description: "Send and receive messages through a Telegram bot.",
|
|
14068
|
+
logoUrl: "https://t0.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://telegram.org/&size=64",
|
|
14069
|
+
category: "messaging",
|
|
14070
|
+
protocol: "openapi",
|
|
14071
|
+
baseUrl: "https://api.telegram.org",
|
|
14072
|
+
authMode: "api_key",
|
|
14073
|
+
placement: { kind: "bearer" },
|
|
14074
|
+
scopes: []
|
|
14075
|
+
};
|
|
14076
|
+
}));
|
|
14077
|
+
//#endregion
|
|
14078
|
+
//#region ../../libs/shared/connect-registry/src/lib/catalog/whatsapp/whatsapp.connector.ts
|
|
14079
|
+
var WHATSAPP_CONNECTOR;
|
|
14080
|
+
var init_whatsapp_connector = __esmMin((() => {
|
|
14081
|
+
WHATSAPP_CONNECTOR = {
|
|
14082
|
+
id: "whatsapp",
|
|
14083
|
+
displayName: "WhatsApp",
|
|
14084
|
+
description: "Send and receive messages through a WhatsApp bot.",
|
|
14085
|
+
logoUrl: "https://t0.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://www.whatsapp.com/&size=64",
|
|
14086
|
+
category: "messaging",
|
|
14087
|
+
protocol: "openapi",
|
|
14088
|
+
baseUrl: "https://api.whatsapp.com/v1",
|
|
14089
|
+
authMode: "api_key",
|
|
14090
|
+
placement: { kind: "bearer" },
|
|
14091
|
+
scopes: []
|
|
14092
|
+
};
|
|
14093
|
+
}));
|
|
14094
|
+
//#endregion
|
|
13900
14095
|
//#region ../../libs/shared/connect-registry/src/lib/catalog/built-in-catalog.ts
|
|
13901
14096
|
/**
|
|
13902
14097
|
* Seed `store` with the built-in catalog. Returns `loadFromJson`'s outcome so the
|
|
@@ -13908,91 +14103,15 @@ function loadBuiltInCatalog(store) {
|
|
|
13908
14103
|
}
|
|
13909
14104
|
var BUILT_IN_CONNECTOR_DOCS;
|
|
13910
14105
|
var init_built_in_catalog = __esmMin((() => {
|
|
14106
|
+
init_gmail_connector();
|
|
14107
|
+
init_outlook_connector();
|
|
14108
|
+
init_telegram_connector();
|
|
14109
|
+
init_whatsapp_connector();
|
|
13911
14110
|
BUILT_IN_CONNECTOR_DOCS = [
|
|
13912
|
-
|
|
13913
|
-
|
|
13914
|
-
|
|
13915
|
-
|
|
13916
|
-
logoUrl: "https://t0.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://mail.google.com&size=64",
|
|
13917
|
-
category: "email",
|
|
13918
|
-
protocol: "openapi",
|
|
13919
|
-
baseUrl: "https://gmail.googleapis.com/gmail/v1/users/me",
|
|
13920
|
-
authMode: "oauth",
|
|
13921
|
-
placement: { kind: "bearer" },
|
|
13922
|
-
scopes: [
|
|
13923
|
-
"openid",
|
|
13924
|
-
"email",
|
|
13925
|
-
"profile",
|
|
13926
|
-
"https://www.googleapis.com/auth/gmail.readonly",
|
|
13927
|
-
"https://www.googleapis.com/auth/gmail.send"
|
|
13928
|
-
],
|
|
13929
|
-
authorizeUrl: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
13930
|
-
tokenUrl: "https://oauth2.googleapis.com/token",
|
|
13931
|
-
authorizeParams: {
|
|
13932
|
-
access_type: "offline",
|
|
13933
|
-
prompt: "consent"
|
|
13934
|
-
},
|
|
13935
|
-
specSource: {
|
|
13936
|
-
kind: "url",
|
|
13937
|
-
url: "https://api.apis.guru/v2/specs/googleapis.com/gmail/v1/openapi.json"
|
|
13938
|
-
},
|
|
13939
|
-
triggers: [{
|
|
13940
|
-
id: "message-received",
|
|
13941
|
-
displayName: "Message received",
|
|
13942
|
-
description: "Fires when a new message arrives in the inbox.",
|
|
13943
|
-
sampleData: {
|
|
13944
|
-
messageId: "18e0a1b2c3d4e5f6",
|
|
13945
|
-
threadId: "18e0a1b2c3d4e5f6",
|
|
13946
|
-
from: "Ada Lovelace <ada@example.com>",
|
|
13947
|
-
to: "agent@stackbone.ai",
|
|
13948
|
-
subject: "Quarterly report",
|
|
13949
|
-
snippet: "Here is the quarterly report you asked for…",
|
|
13950
|
-
date: "Mon, 10 Jun 2024 09:15:00 +0000",
|
|
13951
|
-
raw: {
|
|
13952
|
-
messageId: "18e0a1b2c3d4e5f6",
|
|
13953
|
-
threadId: "18e0a1b2c3d4e5f6",
|
|
13954
|
-
historyId: "987654"
|
|
13955
|
-
}
|
|
13956
|
-
},
|
|
13957
|
-
poll: {
|
|
13958
|
-
kind: "strategy",
|
|
13959
|
-
strategy: "gmail.history"
|
|
13960
|
-
}
|
|
13961
|
-
}]
|
|
13962
|
-
},
|
|
13963
|
-
{
|
|
13964
|
-
id: "outlook",
|
|
13965
|
-
displayName: "Outlook",
|
|
13966
|
-
description: "Send email and read messages from a connected Outlook account.",
|
|
13967
|
-
logoUrl: "https://t0.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=http://microsoft.com&size=64",
|
|
13968
|
-
category: "email",
|
|
13969
|
-
protocol: "openapi",
|
|
13970
|
-
baseUrl: "https://graph.microsoft.com/v1.0",
|
|
13971
|
-
authMode: "oauth",
|
|
13972
|
-
placement: { kind: "bearer" },
|
|
13973
|
-
scopes: [
|
|
13974
|
-
"openid",
|
|
13975
|
-
"email",
|
|
13976
|
-
"profile",
|
|
13977
|
-
"Mail.Read",
|
|
13978
|
-
"Mail.Send",
|
|
13979
|
-
"offline_access"
|
|
13980
|
-
],
|
|
13981
|
-
authorizeUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
|
|
13982
|
-
tokenUrl: "https://login.microsoftonline.com/common/oauth2/v2.0/token"
|
|
13983
|
-
},
|
|
13984
|
-
{
|
|
13985
|
-
id: "telegram",
|
|
13986
|
-
displayName: "Telegram",
|
|
13987
|
-
description: "Send and receive messages through a Telegram bot.",
|
|
13988
|
-
logoUrl: "https://t0.gstatic.com/faviconV2?client=SOCIAL&type=FAVICON&fallback_opts=TYPE,SIZE,URL&url=https://telegram.org/&size=64",
|
|
13989
|
-
category: "messaging",
|
|
13990
|
-
protocol: "openapi",
|
|
13991
|
-
baseUrl: "https://api.telegram.org",
|
|
13992
|
-
authMode: "api_key",
|
|
13993
|
-
placement: { kind: "bearer" },
|
|
13994
|
-
scopes: []
|
|
13995
|
-
}
|
|
14111
|
+
GMAIL_CONNECTOR,
|
|
14112
|
+
OUTLOOK_CONNECTOR,
|
|
14113
|
+
TELEGRAM_CONNECTOR,
|
|
14114
|
+
WHATSAPP_CONNECTOR
|
|
13996
14115
|
];
|
|
13997
14116
|
}));
|
|
13998
14117
|
//#endregion
|
|
@@ -14565,14 +14684,17 @@ function latestTimestamp(items, field) {
|
|
|
14565
14684
|
function createDeclarativePoll(spec) {
|
|
14566
14685
|
return async (ctx, cursor) => {
|
|
14567
14686
|
const baseArgs = { ...spec.list.args ?? {} };
|
|
14568
|
-
if (cursor !== null && cursor !== void 0) if (spec.cursor.kind === "timestamp") baseArgs[spec.cursor.param] = cursor;
|
|
14687
|
+
if (cursor !== null && cursor !== void 0) if (spec.cursor.kind === "timestamp") baseArgs[spec.cursor.param] = spec.cursor.cursorTemplate ? spec.cursor.cursorTemplate.replace("{cursor}", String(cursor)) : cursor;
|
|
14569
14688
|
else baseArgs[spec.cursor.requestParam] = cursor;
|
|
14570
14689
|
const rawItems = [];
|
|
14571
14690
|
let opaqueNext;
|
|
14572
14691
|
let pageToken;
|
|
14573
14692
|
for (let page = 0; page < MAX_PAGES; page += 1) {
|
|
14574
14693
|
const args = { ...baseArgs };
|
|
14575
|
-
if (
|
|
14694
|
+
if (spec.list.pageSkip) {
|
|
14695
|
+
args[spec.list.pageSkip.pageSizeParam] = spec.list.pageSkip.stride;
|
|
14696
|
+
if (page > 0) args[spec.list.pageSkip.param] = page * spec.list.pageSkip.stride;
|
|
14697
|
+
} else if (pageToken !== null && pageToken !== void 0 && spec.list.pageToken) args[spec.list.pageToken.requestParam] = pageToken;
|
|
14576
14698
|
const response = await ctx.runOperation(spec.list.operationId, args);
|
|
14577
14699
|
const items = getPath(response, spec.list.itemsPath);
|
|
14578
14700
|
if (Array.isArray(items)) rawItems.push(...items);
|
|
@@ -14580,8 +14702,12 @@ function createDeclarativePoll(spec) {
|
|
|
14580
14702
|
const next = getPath(response, spec.cursor.responsePath);
|
|
14581
14703
|
if (next !== null && next !== void 0) opaqueNext = next;
|
|
14582
14704
|
}
|
|
14583
|
-
|
|
14584
|
-
|
|
14705
|
+
if (spec.list.pageSkip) {
|
|
14706
|
+
if (!Array.isArray(items) || items.length < spec.list.pageSkip.stride) break;
|
|
14707
|
+
} else {
|
|
14708
|
+
pageToken = spec.list.pageToken ? getPath(response, spec.list.pageToken.responsePath) : void 0;
|
|
14709
|
+
if (pageToken === null || pageToken === void 0) break;
|
|
14710
|
+
}
|
|
14585
14711
|
}
|
|
14586
14712
|
let items = rawItems;
|
|
14587
14713
|
if (spec.item) {
|
|
@@ -14607,6 +14733,113 @@ var init_declarative_poll = __esmMin((() => {
|
|
|
14607
14733
|
MAX_PAGES = 100;
|
|
14608
14734
|
}));
|
|
14609
14735
|
//#endregion
|
|
14736
|
+
//#region ../../libs/shared/connect-registry/src/lib/catalog/gmail/gmail.history-strategy.ts
|
|
14737
|
+
function isGmailCursor(cursor) {
|
|
14738
|
+
return typeof cursor === "object" && cursor !== null && typeof cursor.historyId === "string" && cursor.historyId.length > 0;
|
|
14739
|
+
}
|
|
14740
|
+
/** Read a single header value (case-insensitive) off a Gmail message payload. */
|
|
14741
|
+
function header(message, name) {
|
|
14742
|
+
const match = (message.payload?.headers ?? []).find((h) => (h.name ?? "").toLowerCase() === name.toLowerCase());
|
|
14743
|
+
return typeof match?.value === "string" ? match.value : "";
|
|
14744
|
+
}
|
|
14745
|
+
/** Fetch one message (metadata format) and normalize it to a poll item. */
|
|
14746
|
+
async function fetchMessageEvent(ctx, id) {
|
|
14747
|
+
const message = await ctx.runOperation("gmail.users.messages.get", {
|
|
14748
|
+
userId: USER_ID,
|
|
14749
|
+
id,
|
|
14750
|
+
format: "metadata"
|
|
14751
|
+
});
|
|
14752
|
+
const payload = {
|
|
14753
|
+
messageId: message.id ?? id,
|
|
14754
|
+
threadId: message.threadId ?? "",
|
|
14755
|
+
from: header(message, "From"),
|
|
14756
|
+
to: header(message, "To"),
|
|
14757
|
+
subject: header(message, "Subject"),
|
|
14758
|
+
snippet: typeof message.snippet === "string" ? message.snippet : "",
|
|
14759
|
+
date: header(message, "Date"),
|
|
14760
|
+
raw: {
|
|
14761
|
+
messageId: message.id ?? id,
|
|
14762
|
+
threadId: message.threadId ?? "",
|
|
14763
|
+
historyId: typeof message.historyId === "string" ? message.historyId : null
|
|
14764
|
+
}
|
|
14765
|
+
};
|
|
14766
|
+
return {
|
|
14767
|
+
id: message.id ?? id,
|
|
14768
|
+
payload
|
|
14769
|
+
};
|
|
14770
|
+
}
|
|
14771
|
+
function readHistoryId(event) {
|
|
14772
|
+
const raw = (event?.payload)?.raw;
|
|
14773
|
+
return raw && typeof raw.historyId === "string" ? raw.historyId : null;
|
|
14774
|
+
}
|
|
14775
|
+
/**
|
|
14776
|
+
* Bootstrap path (empty cursor): list the most recent inbox messages, normalize
|
|
14777
|
+
* them, and seed the cursor from the newest message's `historyId`. Dedup is the
|
|
14778
|
+
* platform's job (by message id), so a first poll legitimately returns the recent
|
|
14779
|
+
* window and the next poll resumes from the history API.
|
|
14780
|
+
*/
|
|
14781
|
+
async function bootstrap(ctx) {
|
|
14782
|
+
const items = await mapWithConcurrency(((await ctx.runOperation("gmail.users.messages.list", {
|
|
14783
|
+
userId: USER_ID,
|
|
14784
|
+
maxResults: BOOTSTRAP_MAX_RESULTS,
|
|
14785
|
+
labelIds: "INBOX"
|
|
14786
|
+
})).messages ?? []).map((m) => m.id).filter((id) => typeof id === "string" && id.length > 0), 6, (id) => fetchMessageEvent(ctx, id));
|
|
14787
|
+
const seedHistoryId = readHistoryId(items[0]);
|
|
14788
|
+
return {
|
|
14789
|
+
items,
|
|
14790
|
+
nextCursor: seedHistoryId ? { historyId: seedHistoryId } : null
|
|
14791
|
+
};
|
|
14792
|
+
}
|
|
14793
|
+
/**
|
|
14794
|
+
* Incremental path (valid cursor): pull history records added since the persisted
|
|
14795
|
+
* `historyId` via `history.list`, drain EVERY page (so messages on pages 2+ are
|
|
14796
|
+
* never skipped when the cursor advances), normalize each new arrival, and move
|
|
14797
|
+
* the cursor to the response's latest `historyId`.
|
|
14798
|
+
*/
|
|
14799
|
+
async function pollFromCursor(ctx, cursor) {
|
|
14800
|
+
const addedIds = [];
|
|
14801
|
+
let latestHistoryId = cursor.historyId;
|
|
14802
|
+
let pageToken;
|
|
14803
|
+
for (let page = 0; page < MAX_HISTORY_PAGES; page += 1) {
|
|
14804
|
+
const history = await ctx.runOperation("gmail.users.history.list", {
|
|
14805
|
+
userId: USER_ID,
|
|
14806
|
+
startHistoryId: cursor.historyId,
|
|
14807
|
+
historyTypes: "messageAdded",
|
|
14808
|
+
labelId: "INBOX",
|
|
14809
|
+
...pageToken ? { pageToken } : {}
|
|
14810
|
+
});
|
|
14811
|
+
for (const record of history.history ?? []) for (const added of record.messagesAdded ?? []) {
|
|
14812
|
+
const id = added.message?.id;
|
|
14813
|
+
if (typeof id === "string" && id.length > 0) addedIds.push(id);
|
|
14814
|
+
}
|
|
14815
|
+
if (typeof history.historyId === "string" && history.historyId.length > 0) latestHistoryId = history.historyId;
|
|
14816
|
+
if (typeof history.nextPageToken === "string" && history.nextPageToken.length > 0) pageToken = history.nextPageToken;
|
|
14817
|
+
else break;
|
|
14818
|
+
}
|
|
14819
|
+
return {
|
|
14820
|
+
items: await mapWithConcurrency(addedIds, 6, (id) => fetchMessageEvent(ctx, id)),
|
|
14821
|
+
nextCursor: { historyId: latestHistoryId }
|
|
14822
|
+
};
|
|
14823
|
+
}
|
|
14824
|
+
var USER_ID, BOOTSTRAP_MAX_RESULTS, MAX_HISTORY_PAGES, gmailHistoryPoll;
|
|
14825
|
+
var init_gmail_history_strategy = __esmMin((() => {
|
|
14826
|
+
init_concurrency();
|
|
14827
|
+
USER_ID = "me";
|
|
14828
|
+
BOOTSTRAP_MAX_RESULTS = 25;
|
|
14829
|
+
MAX_HISTORY_PAGES = 100;
|
|
14830
|
+
gmailHistoryPoll = async (ctx, cursor) => {
|
|
14831
|
+
if (!isGmailCursor(cursor)) return bootstrap(ctx);
|
|
14832
|
+
return pollFromCursor(ctx, cursor);
|
|
14833
|
+
};
|
|
14834
|
+
}));
|
|
14835
|
+
//#endregion
|
|
14836
|
+
//#region ../../libs/shared/connect-registry/src/lib/catalog/built-in-strategies.ts
|
|
14837
|
+
var BUILT_IN_STRATEGIES;
|
|
14838
|
+
var init_built_in_strategies = __esmMin((() => {
|
|
14839
|
+
init_gmail_history_strategy();
|
|
14840
|
+
BUILT_IN_STRATEGIES = { "gmail.history": gmailHistoryPoll };
|
|
14841
|
+
}));
|
|
14842
|
+
//#endregion
|
|
14610
14843
|
//#region ../../libs/shared/connect-registry/src/index.ts
|
|
14611
14844
|
var init_src$3 = __esmMin((() => {
|
|
14612
14845
|
init_types$1();
|
|
@@ -14619,6 +14852,7 @@ var init_src$3 = __esmMin((() => {
|
|
|
14619
14852
|
init_trigger_descriptor();
|
|
14620
14853
|
init_declarative_poll();
|
|
14621
14854
|
init_concurrency();
|
|
14855
|
+
init_built_in_strategies();
|
|
14622
14856
|
}));
|
|
14623
14857
|
//#endregion
|
|
14624
14858
|
//#region ../../libs/platform/connect-broker/src/lib/executor/spec-introspection.ts
|
|
@@ -16692,8 +16926,14 @@ function invalidRequest(message) {
|
|
|
16692
16926
|
}
|
|
16693
16927
|
//#endregion
|
|
16694
16928
|
//#region ../../libs/runtime/agent-emulator/src/lib/deep-agents/registry.ts
|
|
16695
|
-
var DEEP_AGENTS_WELL_KNOWN_DIR, isPlainRecord, readConfigStrings, toMetadata, isDeepAgentDefinition, bundleAndLoad, loadPrebuilt, createDeepAgentRegistry, errMessage$9, matchChangedPathsToAgents;
|
|
16929
|
+
var SYSTEM_DEEP_AGENTS, isInternalDeepAgent, DEEP_AGENTS_WELL_KNOWN_DIR, isPlainRecord, readConfigStrings, toMetadata, isDeepAgentDefinition, bundleAndLoad, loadPrebuilt, createDeepAgentRegistry, errMessage$9, matchChangedPathsToAgents;
|
|
16696
16930
|
var init_registry$1 = __esmMin((() => {
|
|
16931
|
+
SYSTEM_DEEP_AGENTS = new Set(["rag-ingest"]);
|
|
16932
|
+
isInternalDeepAgent = (agent) => {
|
|
16933
|
+
if (agent.$internal === false) return false;
|
|
16934
|
+
if (agent.$internal === true) return true;
|
|
16935
|
+
return SYSTEM_DEEP_AGENTS.has(agent.name);
|
|
16936
|
+
};
|
|
16697
16937
|
DEEP_AGENTS_WELL_KNOWN_DIR = ".well-known/deep-agents";
|
|
16698
16938
|
isPlainRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16699
16939
|
readConfigStrings = (config) => {
|
|
@@ -16785,7 +17025,8 @@ var init_registry$1 = __esmMin((() => {
|
|
|
16785
17025
|
metadata: toMetadata(def)
|
|
16786
17026
|
},
|
|
16787
17027
|
createGraph: def.createGraph.bind(def),
|
|
16788
|
-
supportsCheckpointer: def.capabilities?.checkpointer === true
|
|
17028
|
+
supportsCheckpointer: def.capabilities?.checkpointer === true,
|
|
17029
|
+
$internal: isInternalDeepAgent(agent)
|
|
16789
17030
|
});
|
|
16790
17031
|
logger.info(`deep agent "${agent.name}" ready (model ${def.metadata.model}).`);
|
|
16791
17032
|
return true;
|
|
@@ -16826,7 +17067,7 @@ var init_registry$1 = __esmMin((() => {
|
|
|
16826
17067
|
return {
|
|
16827
17068
|
list: () => {
|
|
16828
17069
|
const checkpointerReady = opts.checkpointer?.status?.() === "ready";
|
|
16829
|
-
return [...registered.values()].map((e) => ({
|
|
17070
|
+
return [...registered.values()].filter((e) => !e.$internal).map((e) => ({
|
|
16830
17071
|
name: e.view.name,
|
|
16831
17072
|
metadata: e.view.metadata,
|
|
16832
17073
|
durable: e.supportsCheckpointer && checkpointerReady
|
|
@@ -22237,13 +22478,19 @@ var init_workflow_step_world_port = __esmMin((() => {
|
|
|
22237
22478
|
}));
|
|
22238
22479
|
//#endregion
|
|
22239
22480
|
//#region ../../libs/runtime/agent-emulator/src/lib/workflow/registry.ts
|
|
22240
|
-
var hasDeclaredSchema, workflowStartTrigger, buildManifest;
|
|
22481
|
+
var hasDeclaredSchema, workflowStartTrigger, SYSTEM_WORKFLOWS, isInternalWorkflow, buildManifest;
|
|
22241
22482
|
var init_registry = __esmMin((() => {
|
|
22242
22483
|
hasDeclaredSchema = (pair) => pair != null && (pair.input != null || pair.output != null);
|
|
22243
22484
|
workflowStartTrigger = (name) => `POST /api/workflows/${name}/start`;
|
|
22485
|
+
SYSTEM_WORKFLOWS = new Set(["rag-ingest"]);
|
|
22486
|
+
isInternalWorkflow = (workflow) => {
|
|
22487
|
+
if (workflow.$internal === false) return false;
|
|
22488
|
+
if (workflow.$internal === true) return true;
|
|
22489
|
+
return SYSTEM_WORKFLOWS.has(workflow.name);
|
|
22490
|
+
};
|
|
22244
22491
|
buildManifest = (input) => ({
|
|
22245
22492
|
agents: [],
|
|
22246
|
-
workflows: input.workspace.workflows.map((w) => {
|
|
22493
|
+
workflows: input.workspace.workflows.filter((w) => !isInternalWorkflow(w)).map((w) => {
|
|
22247
22494
|
const steps = input.workflowSteps?.get(w.name);
|
|
22248
22495
|
return {
|
|
22249
22496
|
name: w.name,
|
|
@@ -22485,6 +22732,28 @@ var init_workflow_start_service = __esmMin((() => {
|
|
|
22485
22732
|
return triggerWorkflowStartAndWait(deps, name, input);
|
|
22486
22733
|
}
|
|
22487
22734
|
});
|
|
22735
|
+
}));
|
|
22736
|
+
//#endregion
|
|
22737
|
+
//#region ../../libs/runtime/agent-emulator/src/lib/workflow/approval-recorder-bridge.ts
|
|
22738
|
+
var createApprovalRecorder;
|
|
22739
|
+
var init_approval_recorder_bridge = __esmMin((() => {
|
|
22740
|
+
createApprovalRecorder = (deps) => ({ async request(args) {
|
|
22741
|
+
const context = deps.getInvocationContext?.();
|
|
22742
|
+
const enriched = { ...args };
|
|
22743
|
+
if (context?.runId !== void 0) enriched["runId"] = context.runId;
|
|
22744
|
+
if (context?.requestedByStepId !== void 0) enriched["requestedByStepId"] = context.requestedByStepId;
|
|
22745
|
+
try {
|
|
22746
|
+
const result = await deps.request(enriched);
|
|
22747
|
+
if (result.error) {
|
|
22748
|
+
const code = result.error.code ?? "approval_persist_failed";
|
|
22749
|
+
const message = result.error.message ?? "Failed to write the approval to the agent database.";
|
|
22750
|
+
throw new Error(`requestApproval could not persist the approvals row (${code}): ${message} The workflow step will retry — a HITL decision is never quietly lost.`);
|
|
22751
|
+
}
|
|
22752
|
+
} catch (err) {
|
|
22753
|
+
console.error("[approval-recorder] failed to persist approvals row:", err instanceof Error ? err.message : String(err));
|
|
22754
|
+
throw err;
|
|
22755
|
+
}
|
|
22756
|
+
} });
|
|
22488
22757
|
})), DEFAULT_TZ, TICK_JOB_NAME$1, DECL_PREFIX, DYN_PREFIX, declSchedulerId, dynSchedulerId, planDeclarativeReconcile, expandDeclaredSchedules, parseSchedulerId, consoleLogger$2, WorkflowCronScheduler, createWorkflowSchedulerBridge;
|
|
22489
22758
|
var init_workflow_cron_scheduler = __esmMin((() => {
|
|
22490
22759
|
DEFAULT_TZ = "UTC";
|
|
@@ -23054,111 +23323,11 @@ var init_intake_scheduler = __esmMin((() => {
|
|
|
23054
23323
|
};
|
|
23055
23324
|
}));
|
|
23056
23325
|
//#endregion
|
|
23057
|
-
//#region ../../libs/runtime/agent-emulator/src/lib/connect-inbound/gmail-history-strategy.ts
|
|
23058
|
-
function isGmailCursor(cursor) {
|
|
23059
|
-
return typeof cursor === "object" && cursor !== null && typeof cursor.historyId === "string" && cursor.historyId.length > 0;
|
|
23060
|
-
}
|
|
23061
|
-
/** Read a single header value (case-insensitive) off a Gmail message payload. */
|
|
23062
|
-
function header(message, name) {
|
|
23063
|
-
const match = (message.payload?.headers ?? []).find((h) => (h.name ?? "").toLowerCase() === name.toLowerCase());
|
|
23064
|
-
return typeof match?.value === "string" ? match.value : "";
|
|
23065
|
-
}
|
|
23066
|
-
/** Fetch one message (metadata format) and normalize it to a poll item. */
|
|
23067
|
-
async function fetchMessageEvent(ctx, id) {
|
|
23068
|
-
const message = await ctx.runOperation("gmail.users.messages.get", {
|
|
23069
|
-
userId: USER_ID,
|
|
23070
|
-
id,
|
|
23071
|
-
format: "metadata"
|
|
23072
|
-
});
|
|
23073
|
-
const payload = {
|
|
23074
|
-
messageId: message.id ?? id,
|
|
23075
|
-
threadId: message.threadId ?? "",
|
|
23076
|
-
from: header(message, "From"),
|
|
23077
|
-
to: header(message, "To"),
|
|
23078
|
-
subject: header(message, "Subject"),
|
|
23079
|
-
snippet: typeof message.snippet === "string" ? message.snippet : "",
|
|
23080
|
-
date: header(message, "Date"),
|
|
23081
|
-
raw: {
|
|
23082
|
-
messageId: message.id ?? id,
|
|
23083
|
-
threadId: message.threadId ?? "",
|
|
23084
|
-
historyId: typeof message.historyId === "string" ? message.historyId : null
|
|
23085
|
-
}
|
|
23086
|
-
};
|
|
23087
|
-
return {
|
|
23088
|
-
id: message.id ?? id,
|
|
23089
|
-
payload
|
|
23090
|
-
};
|
|
23091
|
-
}
|
|
23092
|
-
function readHistoryId(event) {
|
|
23093
|
-
const raw = (event?.payload)?.raw;
|
|
23094
|
-
return raw && typeof raw.historyId === "string" ? raw.historyId : null;
|
|
23095
|
-
}
|
|
23096
|
-
/**
|
|
23097
|
-
* Bootstrap path (empty cursor): list the most recent inbox messages, normalize
|
|
23098
|
-
* them, and seed the cursor from the newest message's `historyId`. Dedup is the
|
|
23099
|
-
* platform's job (by message id), so a first poll legitimately returns the recent
|
|
23100
|
-
* window and the next poll resumes from the history API.
|
|
23101
|
-
*/
|
|
23102
|
-
async function bootstrap(ctx) {
|
|
23103
|
-
const items = await mapWithConcurrency(((await ctx.runOperation("gmail.users.messages.list", {
|
|
23104
|
-
userId: USER_ID,
|
|
23105
|
-
maxResults: BOOTSTRAP_MAX_RESULTS,
|
|
23106
|
-
labelIds: "INBOX"
|
|
23107
|
-
})).messages ?? []).map((m) => m.id).filter((id) => typeof id === "string" && id.length > 0), 6, (id) => fetchMessageEvent(ctx, id));
|
|
23108
|
-
const seedHistoryId = readHistoryId(items[0]);
|
|
23109
|
-
return {
|
|
23110
|
-
items,
|
|
23111
|
-
nextCursor: seedHistoryId ? { historyId: seedHistoryId } : null
|
|
23112
|
-
};
|
|
23113
|
-
}
|
|
23114
|
-
/**
|
|
23115
|
-
* Incremental path (valid cursor): pull history records added since the persisted
|
|
23116
|
-
* `historyId` via `history.list`, drain EVERY page (so messages on pages 2+ are
|
|
23117
|
-
* never skipped when the cursor advances), normalize each new arrival, and move
|
|
23118
|
-
* the cursor to the response's latest `historyId`.
|
|
23119
|
-
*/
|
|
23120
|
-
async function pollFromCursor(ctx, cursor) {
|
|
23121
|
-
const addedIds = [];
|
|
23122
|
-
let latestHistoryId = cursor.historyId;
|
|
23123
|
-
let pageToken;
|
|
23124
|
-
for (let page = 0; page < MAX_HISTORY_PAGES; page += 1) {
|
|
23125
|
-
const history = await ctx.runOperation("gmail.users.history.list", {
|
|
23126
|
-
userId: USER_ID,
|
|
23127
|
-
startHistoryId: cursor.historyId,
|
|
23128
|
-
historyTypes: "messageAdded",
|
|
23129
|
-
labelId: "INBOX",
|
|
23130
|
-
...pageToken ? { pageToken } : {}
|
|
23131
|
-
});
|
|
23132
|
-
for (const record of history.history ?? []) for (const added of record.messagesAdded ?? []) {
|
|
23133
|
-
const id = added.message?.id;
|
|
23134
|
-
if (typeof id === "string" && id.length > 0) addedIds.push(id);
|
|
23135
|
-
}
|
|
23136
|
-
if (typeof history.historyId === "string" && history.historyId.length > 0) latestHistoryId = history.historyId;
|
|
23137
|
-
if (typeof history.nextPageToken === "string" && history.nextPageToken.length > 0) pageToken = history.nextPageToken;
|
|
23138
|
-
else break;
|
|
23139
|
-
}
|
|
23140
|
-
return {
|
|
23141
|
-
items: await mapWithConcurrency(addedIds, 6, (id) => fetchMessageEvent(ctx, id)),
|
|
23142
|
-
nextCursor: { historyId: latestHistoryId }
|
|
23143
|
-
};
|
|
23144
|
-
}
|
|
23145
|
-
var USER_ID, BOOTSTRAP_MAX_RESULTS, MAX_HISTORY_PAGES, gmailHistoryPoll;
|
|
23146
|
-
var init_gmail_history_strategy = __esmMin((() => {
|
|
23147
|
-
init_src$3();
|
|
23148
|
-
USER_ID = "me";
|
|
23149
|
-
BOOTSTRAP_MAX_RESULTS = 25;
|
|
23150
|
-
MAX_HISTORY_PAGES = 100;
|
|
23151
|
-
gmailHistoryPoll = async (ctx, cursor) => {
|
|
23152
|
-
if (!isGmailCursor(cursor)) return bootstrap(ctx);
|
|
23153
|
-
return pollFromCursor(ctx, cursor);
|
|
23154
|
-
};
|
|
23155
|
-
}));
|
|
23156
|
-
//#endregion
|
|
23157
23326
|
//#region ../../libs/runtime/agent-emulator/src/lib/connect-inbound/trigger-strategies.ts
|
|
23158
23327
|
var STRATEGIES, resolveStrategy;
|
|
23159
23328
|
var init_trigger_strategies = __esmMin((() => {
|
|
23160
|
-
|
|
23161
|
-
STRATEGIES = {
|
|
23329
|
+
init_src$3();
|
|
23330
|
+
STRATEGIES = { ...BUILT_IN_STRATEGIES };
|
|
23162
23331
|
resolveStrategy = (name) => STRATEGIES[name] ?? null;
|
|
23163
23332
|
}));
|
|
23164
23333
|
//#endregion
|
|
@@ -23389,6 +23558,7 @@ var init_runtime_mount = __esmMin((() => {
|
|
|
23389
23558
|
init_workflow_run_projector();
|
|
23390
23559
|
init_workflow_invoker();
|
|
23391
23560
|
init_workflow_start_service();
|
|
23561
|
+
init_approval_recorder_bridge();
|
|
23392
23562
|
init_workflow_cron_scheduler();
|
|
23393
23563
|
init_workflow_hook_resume();
|
|
23394
23564
|
init_workflow_frame_sse();
|
|
@@ -23468,6 +23638,11 @@ var init_runtime_mount = __esmMin((() => {
|
|
|
23468
23638
|
let setWorkflowStarter;
|
|
23469
23639
|
let setWorkflowScheduler;
|
|
23470
23640
|
let setDeepAgentInvoker;
|
|
23641
|
+
let setAiUsageReporter;
|
|
23642
|
+
let setApprovalRecorder;
|
|
23643
|
+
let approvalRequest;
|
|
23644
|
+
let setConnectorInvoker;
|
|
23645
|
+
let connectorInvoker;
|
|
23471
23646
|
try {
|
|
23472
23647
|
const sdk = await importProject("@stackbone/sdk");
|
|
23473
23648
|
runWithInvocationContext = sdk.runWithInvocationContext;
|
|
@@ -23475,12 +23650,34 @@ var init_runtime_mount = __esmMin((() => {
|
|
|
23475
23650
|
setWorkflowStarter = sdk.setWorkflowStarter;
|
|
23476
23651
|
setWorkflowScheduler = sdk.setWorkflowScheduler;
|
|
23477
23652
|
setDeepAgentInvoker = sdk.setDeepAgentInvoker;
|
|
23653
|
+
setAiUsageReporter = sdk.setAiUsageReporter;
|
|
23654
|
+
setApprovalRecorder = sdk.setApprovalRecorder;
|
|
23655
|
+
setConnectorInvoker = sdk.setConnectorInvoker;
|
|
23656
|
+
connectorInvoker = sdk.createConnectInvoker?.();
|
|
23657
|
+
const ambientStackbone = sdk.stackbone;
|
|
23658
|
+
if (ambientStackbone) approvalRequest = async (args) => {
|
|
23659
|
+
const approval = ambientStackbone.approval;
|
|
23660
|
+
if (!approval?.request) return {
|
|
23661
|
+
data: null,
|
|
23662
|
+
error: {
|
|
23663
|
+
code: "approval_unavailable",
|
|
23664
|
+
message: "The project SDK exposes no ambient approval writer."
|
|
23665
|
+
}
|
|
23666
|
+
};
|
|
23667
|
+
return approval.request(args);
|
|
23668
|
+
};
|
|
23669
|
+
else approvalRequest = void 0;
|
|
23478
23670
|
} catch {
|
|
23479
23671
|
runWithInvocationContext = void 0;
|
|
23480
23672
|
getInvocationContext = void 0;
|
|
23481
23673
|
setWorkflowStarter = void 0;
|
|
23482
23674
|
setWorkflowScheduler = void 0;
|
|
23483
23675
|
setDeepAgentInvoker = void 0;
|
|
23676
|
+
setAiUsageReporter = void 0;
|
|
23677
|
+
setApprovalRecorder = void 0;
|
|
23678
|
+
approvalRequest = void 0;
|
|
23679
|
+
setConnectorInvoker = void 0;
|
|
23680
|
+
connectorInvoker = void 0;
|
|
23484
23681
|
}
|
|
23485
23682
|
const stepUrl = pathToFileURL(resolve(projectRoot, WELL_KNOWN_DIR$2, "step.mjs")).href;
|
|
23486
23683
|
await (runtimeEnv.generation ? import(`${stepUrl}?v=${runtimeEnv.generation}`) : import(stepUrl));
|
|
@@ -23492,7 +23689,12 @@ var init_runtime_mount = __esmMin((() => {
|
|
|
23492
23689
|
resumeHook,
|
|
23493
23690
|
setWorkflowStarter,
|
|
23494
23691
|
setWorkflowScheduler,
|
|
23495
|
-
setDeepAgentInvoker
|
|
23692
|
+
setDeepAgentInvoker,
|
|
23693
|
+
setAiUsageReporter,
|
|
23694
|
+
setApprovalRecorder,
|
|
23695
|
+
approvalRequest,
|
|
23696
|
+
setConnectorInvoker,
|
|
23697
|
+
connectorInvoker
|
|
23496
23698
|
};
|
|
23497
23699
|
};
|
|
23498
23700
|
mountWorkflowRuntime = async (app, opts) => {
|
|
@@ -23578,6 +23780,21 @@ var init_runtime_mount = __esmMin((() => {
|
|
|
23578
23780
|
return invoker(name, input, options);
|
|
23579
23781
|
});
|
|
23580
23782
|
}
|
|
23783
|
+
if (rt.setAiUsageReporter) {
|
|
23784
|
+
const invocations = opts.invocations;
|
|
23785
|
+
rt.setAiUsageReporter((usage) => {
|
|
23786
|
+
const runId = rt.getInvocationContext?.()?.runId;
|
|
23787
|
+
if (!runId || !invocations) return;
|
|
23788
|
+
invocations.addRunTokens(runId, usage).catch((err) => {
|
|
23789
|
+
console.warn(`[ai-usage] token fold failed for run ${runId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
23790
|
+
});
|
|
23791
|
+
});
|
|
23792
|
+
}
|
|
23793
|
+
if (rt.setApprovalRecorder && rt.approvalRequest) rt.setApprovalRecorder(createApprovalRecorder({
|
|
23794
|
+
request: rt.approvalRequest,
|
|
23795
|
+
...rt.getInvocationContext ? { getInvocationContext: rt.getInvocationContext } : {}
|
|
23796
|
+
}));
|
|
23797
|
+
if (rt.setConnectorInvoker && rt.connectorInvoker) rt.setConnectorInvoker(rt.connectorInvoker);
|
|
23581
23798
|
return rt;
|
|
23582
23799
|
}).catch((err) => {
|
|
23583
23800
|
runtimePromise = null;
|
|
@@ -23808,7 +24025,11 @@ var init_runtime_mount = __esmMin((() => {
|
|
|
23808
24025
|
await cronScheduler?.close();
|
|
23809
24026
|
await intakeRuntime?.close();
|
|
23810
24027
|
if (runtimePromise) try {
|
|
23811
|
-
|
|
24028
|
+
const rt = await runtimePromise;
|
|
24029
|
+
rt.setDeepAgentInvoker?.(void 0);
|
|
24030
|
+
rt.setAiUsageReporter?.(void 0);
|
|
24031
|
+
rt.setApprovalRecorder?.(void 0);
|
|
24032
|
+
rt.setConnectorInvoker?.(void 0);
|
|
23812
24033
|
} catch {}
|
|
23813
24034
|
},
|
|
23814
24035
|
triggerWorkflowStart: (name, input) => triggerWorkflowStart(startDeps, name, input),
|
|
@@ -30827,6 +31048,62 @@ var findWorkflowFiles = async (projectRoot, extraModules = []) => {
|
|
|
30827
31048
|
return files;
|
|
30828
31049
|
};
|
|
30829
31050
|
/**
|
|
31051
|
+
* Scan the final `workflow.vm.js` text for any `require(...)` call and throw an
|
|
31052
|
+
* actionable error if one is found.
|
|
31053
|
+
*
|
|
31054
|
+
* The workflow VM bundle runs on `node:vm`, which has NO `require`. A `require(`
|
|
31055
|
+
* token surviving into the bundle means something reachable from a workflow body
|
|
31056
|
+
* (a helper, a transitive import) dragged a Node-only dependency into the VM graph
|
|
31057
|
+
* — the Workflow SDK (WDK) compiler inlines the whole module, and the inlined
|
|
31058
|
+
* `require()` throws `ReferenceError: require is not defined` at instantiation,
|
|
31059
|
+
* crashing EVERY workflow in the project with an opaque `USER_ERROR` / "Unknown
|
|
31060
|
+
* error" (the bug this guard makes impossible to ship silently).
|
|
31061
|
+
*
|
|
31062
|
+
* Pure + exported so it is unit-testable in isolation (prior art:
|
|
31063
|
+
* `foldSchemasIntoManifest`). False-positive discipline: it matches `require(`
|
|
31064
|
+
* only as a CALL shape, not the substring inside a comment or a string literal
|
|
31065
|
+
* that is not actually invoked — the VM bundle is generated code, so a literal
|
|
31066
|
+
* `require(` in a string is still a smell worth flagging, but the guard reports
|
|
31067
|
+
* the surrounding context so a human can tell a real leak from a benign mention.
|
|
31068
|
+
*/
|
|
31069
|
+
var assertNoLeakedNodeRequire = (bundleText) => {
|
|
31070
|
+
const requirePattern = /require\s*\(\s*['"`]/g;
|
|
31071
|
+
const matches = [];
|
|
31072
|
+
const lines = bundleText.split("\n");
|
|
31073
|
+
for (const match of bundleText.matchAll(requirePattern)) {
|
|
31074
|
+
const index = match.index ?? 0;
|
|
31075
|
+
let line = 1;
|
|
31076
|
+
let column = 1;
|
|
31077
|
+
let consumed = 0;
|
|
31078
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
31079
|
+
const lineText = lines[i];
|
|
31080
|
+
if (lineText === void 0) break;
|
|
31081
|
+
const lineEnd = consumed + lineText.length + 1;
|
|
31082
|
+
if (index < lineEnd) {
|
|
31083
|
+
line = i + 1;
|
|
31084
|
+
column = index - consumed + 1;
|
|
31085
|
+
break;
|
|
31086
|
+
}
|
|
31087
|
+
consumed = lineEnd;
|
|
31088
|
+
}
|
|
31089
|
+
const start = Math.max(0, index - 80);
|
|
31090
|
+
const end = Math.min(bundleText.length, index + 120);
|
|
31091
|
+
const snippet = bundleText.slice(start, end).replace(/\s+/g, " ").trim();
|
|
31092
|
+
matches.push({
|
|
31093
|
+
index,
|
|
31094
|
+
line,
|
|
31095
|
+
column,
|
|
31096
|
+
snippet
|
|
31097
|
+
});
|
|
31098
|
+
}
|
|
31099
|
+
if (matches.length === 0) return;
|
|
31100
|
+
const first = matches[0];
|
|
31101
|
+
if (!first) return;
|
|
31102
|
+
const listing = matches.slice(0, 5).map((m, i) => ` ${i + 1}. line ${m.line}:${m.column} …${m.snippet}…`).join("\n");
|
|
31103
|
+
const more = matches.length > 5 ? `\n (and ${matches.length - 5} more)` : "";
|
|
31104
|
+
throw new Error(`Workflow VM bundle contains ${matches.length} require() call(s) — the workflow VM (node:vm) has no \`require\`, so the bundle will crash at instantiation with \`ReferenceError: require is not defined\`, breaking EVERY workflow in this project.\nThis means a Node-only dependency (e.g. node:crypto, the Postgres driver, the OpenAI / AWS SDKs) is reachable from a workflow body or a "use step" that was not properly externalized. The most common cause is a workflow-steps helper that touches Node at module scope — it must reach Node only through a runtime-planted binding (see @stackbone/sdk/workflow-steps/*) or be wrapped in a "use step" that the WDK stubs out of the VM graph.\nFirst occurrence: line ${first.line}:${first.column}\n${listing}${more}\nFix: move the Node-bearing code behind a runtime binding, wrap the call in a "use step" function, or import the helper from @stackbone/sdk/workflow-steps/* (the per-domain entry that the WDK keeps out of the VM body).`);
|
|
31105
|
+
};
|
|
31106
|
+
/**
|
|
30830
31107
|
* Build the workspace's workflows into `<projectRoot>/.well-known/workflow/v1/`:
|
|
30831
31108
|
* - `step.mjs` — steps bundle (runtime external)
|
|
30832
31109
|
* - `workflow.vm.js` — the workflow VM bundle text fed to `workflowEntrypoint`
|
|
@@ -30855,7 +31132,7 @@ var buildWorkflows = async (projectRoot, workflows, logger) => {
|
|
|
30855
31132
|
stepsBundlePath: `./${WELL_KNOWN_DIR}/step.mjs`,
|
|
30856
31133
|
workflowsBundlePath: `./${WELL_KNOWN_DIR}/workflow.vm.js`,
|
|
30857
31134
|
webhookBundlePath: `./${WELL_KNOWN_DIR}/webhook.mjs`,
|
|
30858
|
-
externalPackages: [
|
|
31135
|
+
externalPackages: []
|
|
30859
31136
|
});
|
|
30860
31137
|
const prevCwd = process.cwd();
|
|
30861
31138
|
let manifest;
|
|
@@ -30882,6 +31159,7 @@ var buildWorkflows = async (projectRoot, workflows, logger) => {
|
|
|
30882
31159
|
const streaming = await detectStreamingWorkflows(projectRoot, workflows);
|
|
30883
31160
|
foldSchemasIntoManifest(manifest, workflows, schemas, streaming, schedules);
|
|
30884
31161
|
await writeFile(resolve(wkDir, "workflow.vm.js"), interimBundleText, "utf8");
|
|
31162
|
+
assertNoLeakedNodeRequire(interimBundleText);
|
|
30885
31163
|
await writeFile(resolve(wkDir, "manifest.json"), JSON.stringify(manifest), "utf8");
|
|
30886
31164
|
for (const name of [
|
|
30887
31165
|
"step.mjs",
|
|
@@ -31176,7 +31454,8 @@ var loadWorkspace = async (projectRoot) => {
|
|
|
31176
31454
|
if (!isWorkspace(workspace)) throw new Error(`${configPath} must default-export a workspace with \`agents\` and \`workflows\` arrays (via \`defineWorkspace({ agents, workflows })\`).`);
|
|
31177
31455
|
return {
|
|
31178
31456
|
agents: workspace.agents,
|
|
31179
|
-
workflows: workspace.workflows
|
|
31457
|
+
workflows: workspace.workflows,
|
|
31458
|
+
deepAgents: workspace.deepAgents
|
|
31180
31459
|
};
|
|
31181
31460
|
};
|
|
31182
31461
|
//#endregion
|
|
@@ -31246,10 +31525,11 @@ var discoverDeepAgents = async (root) => {
|
|
|
31246
31525
|
/**
|
|
31247
31526
|
* Derive `{ agents, workflows, deepAgents }` for the workspace rooted at `root`.
|
|
31248
31527
|
* `agents` is always `[]` (there is no server-per-agent runtime). A `stackbone.config.ts`
|
|
31249
|
-
* override wins for workflows
|
|
31250
|
-
*
|
|
31251
|
-
* omitted
|
|
31252
|
-
*
|
|
31528
|
+
* override wins for workflows AND deep agents; when the config declares `deepAgents`,
|
|
31529
|
+
* those win over auto-discovery (use to mark agents as `$internal` or customize the
|
|
31530
|
+
* registry). When omitted, deep agents are discovered by folder convention and
|
|
31531
|
+
* `deepAgents` is omitted entirely when none are found so an empty workspace is
|
|
31532
|
+
* byte-identical to before.
|
|
31253
31533
|
*/
|
|
31254
31534
|
var discoverWorkspace = async (root) => {
|
|
31255
31535
|
const deepAgents = await discoverDeepAgents(root);
|
|
@@ -31257,10 +31537,18 @@ var discoverWorkspace = async (root) => {
|
|
|
31257
31537
|
...ws,
|
|
31258
31538
|
deepAgents
|
|
31259
31539
|
};
|
|
31260
|
-
if (await fileExists$1(resolve(root, "stackbone.config.ts")))
|
|
31261
|
-
|
|
31262
|
-
|
|
31263
|
-
|
|
31540
|
+
if (await fileExists$1(resolve(root, "stackbone.config.ts"))) {
|
|
31541
|
+
const ws = await loadWorkspace(root);
|
|
31542
|
+
const resultDeepAgents = ws.deepAgents ?? deepAgents;
|
|
31543
|
+
const baseResult = {
|
|
31544
|
+
agents: [],
|
|
31545
|
+
workflows: ws.workflows
|
|
31546
|
+
};
|
|
31547
|
+
return resultDeepAgents.length === 0 ? baseResult : {
|
|
31548
|
+
...baseResult,
|
|
31549
|
+
deepAgents: resultDeepAgents
|
|
31550
|
+
};
|
|
31551
|
+
}
|
|
31264
31552
|
return withDeepAgents({
|
|
31265
31553
|
agents: [],
|
|
31266
31554
|
workflows: await discoverWorkflows(root)
|
|
@@ -35174,6 +35462,7 @@ is for offline work or when the relay handshake fails.
|
|
|
35174
35462
|
The emulator enforces an explicit CORS allowlist (no \`*\`). Default origins:
|
|
35175
35463
|
|
|
35176
35464
|
- \`https://app.stackbone.ai\`
|
|
35465
|
+
- \`https://chat.stackbone.ai\`
|
|
35177
35466
|
- \`http://localhost:*\` (any port; covers any local dev server you run)
|
|
35178
35467
|
|
|
35179
35468
|
Add origins **per-repo** via \`stackbone.config.json\` at the project root
|
|
@@ -35185,6 +35474,7 @@ Add origins **per-repo** via \`stackbone.config.json\` at the project root
|
|
|
35185
35474
|
"studio": {
|
|
35186
35475
|
"corsOrigins": [
|
|
35187
35476
|
"https://app.stackbone.ai",
|
|
35477
|
+
"https://chat.stackbone.ai",
|
|
35188
35478
|
"https://staging.stackbone.ai",
|
|
35189
35479
|
"http://localhost:*",
|
|
35190
35480
|
],
|
package/package.json
CHANGED
|
Binary file
|
package/stackbone-cli-0.2.2.tgz
DELETED
|
Binary file
|