openwork-server 0.18.60 → 0.18.62
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/README.md +9 -2
- package/bin/openwork-server.mjs +1 -1
- package/bin/platform.mjs +7 -7
- package/dist/{opencode-plugin-deps-1.18.30.tgz → opencode-plugin-deps-1.18.33.tgz} +0 -0
- package/dist/opencode-plugins/drive-file-tools.js +10 -8
- package/dist/opencode-plugins/openwork-cloud-skills-v2.js +87 -41
- package/dist/opencode-plugins/openwork-context-v2.js +67 -35
- package/dist/opencode-plugins/openwork-extensions-preview.js +9 -7
- package/dist/opencode-plugins/openwork-gateway-quota-v2.js +187 -0
- package/dist/opencode-plugins/openwork-gateway-quota.js +232 -23
- package/dist/opencode-plugins/openwork-provider-sync-v2.js +85 -2
- package/dist/openwork-server.mjs +1234 -371
- package/package.json +2 -2
- package/web/assets/{abnfDiagram-VCTEODGH-D0_4pXEx.js → abnfDiagram-VCTEODGH-DJzrT8Ql.js} +1 -1
- package/web/assets/app-CkmqBm_1.css +32 -0
- package/web/assets/{app-BCXQnJUH.js → app-_2KkkZIM.js} +435 -425
- package/web/assets/{arc-BSTwaImw.js → arc-KehB1xN5.js} +1 -1
- package/web/assets/{architectureDiagram-5GKGNRK7-cXwF0iP0.js → architectureDiagram-5GKGNRK7-C_GL2639.js} +1 -1
- package/web/assets/{artifact-code-view-CUXv3CYK.js → artifact-code-view-CYn_58gV.js} +1 -1
- package/web/assets/{artifact-spreadsheet-editor-CxhNYmjP.js → artifact-spreadsheet-editor-f6V-tYvi.js} +1 -1
- package/web/assets/{artifact-text-editor-k2TGQI-i.js → artifact-text-editor-CiSlW3kl.js} +1 -1
- package/web/assets/{blockDiagram-OSKFZWR5-Cl9p_z8u.js → blockDiagram-OSKFZWR5-DErH-7gY.js} +1 -1
- package/web/assets/{c4Diagram-7LVT6UL2-YQjnoUQ0.js → c4Diagram-7LVT6UL2-aML4z_n9.js} +1 -1
- package/web/assets/channel-7oM0ncHI.js +1 -0
- package/web/assets/{chunk-2Q5K7J3B-YZaSwlzj.js → chunk-2Q5K7J3B-Dw_IH9rW.js} +1 -1
- package/web/assets/{chunk-5VM5RSS4-BICC_wIw.js → chunk-5VM5RSS4-aeJEQ945.js} +1 -1
- package/web/assets/{chunk-F27PBJKO-CBxmcmxs.js → chunk-F27PBJKO-hZwti-Oc.js} +1 -1
- package/web/assets/{chunk-HLEWEB6X-2h2z7zt8.js → chunk-HLEWEB6X-JFNzm3Ge.js} +1 -1
- package/web/assets/{chunk-JWPE2WC7-BnAMOpXl.js → chunk-JWPE2WC7-B34hvYk7.js} +1 -1
- package/web/assets/{chunk-POPQ4Y6H-pvDYQBBM.js → chunk-POPQ4Y6H-CDqgEp-q.js} +1 -1
- package/web/assets/{chunk-SVP7TREG-QuKLl3v0.js → chunk-SVP7TREG-B65ta9aQ.js} +1 -1
- package/web/assets/{chunk-XXDRQBXY-4Bt9wCBO.js → chunk-XXDRQBXY-DjTi6c9m.js} +1 -1
- package/web/assets/{chunk-ZLD2IHE6-C_RSrkqU.js → chunk-ZLD2IHE6-CbviXFvb.js} +1 -1
- package/web/assets/classDiagram-CYGNFDIV-BkidFauP.js +1 -0
- package/web/assets/classDiagram-v2-TLXNO2FR-BkidFauP.js +1 -0
- package/web/assets/{cose-bilkent-JH36ORCC-CciOYQb4.js → cose-bilkent-JH36ORCC-Cl9SO5zd.js} +1 -1
- package/web/assets/{cynefin-OW5HDTMX-k8-mUlq4.js → cynefin-OW5HDTMX-CAcz2tHt.js} +1 -1
- package/web/assets/{cynefinDiagram-5FMLGOSQ-D1qAHzq3.js → cynefinDiagram-5FMLGOSQ-BJHft4FO.js} +1 -1
- package/web/assets/{dagre-OS7QT2EB-BP1VuF_z.js → dagre-OS7QT2EB-DbdnY1uS.js} +1 -1
- package/web/assets/{diagram-S7CK7UJ4-crXkWleC.js → diagram-S7CK7UJ4-C07WD5Lc.js} +1 -1
- package/web/assets/{diagram-UQ7AKVKN-CtHAmCY-.js → diagram-UQ7AKVKN-D8VCjq9x.js} +1 -1
- package/web/assets/{diagram-VSXAHHWV-C-Fhuwy8.js → diagram-VSXAHHWV-D1XSfMnK.js} +1 -1
- package/web/assets/{diagram-VX7I27RA-DkRkNPuj.js → diagram-VX7I27RA-3GZe-yrf.js} +1 -1
- package/web/assets/{diagram-Z3DM3KII-DVERPCFS.js → diagram-Z3DM3KII-CI43WcIB.js} +1 -1
- package/web/assets/{ebnfDiagram-PWID7BFC-PrSifYGF.js → ebnfDiagram-PWID7BFC-CTzouade.js} +1 -1
- package/web/assets/{erDiagram-2YWLMYGG-D8-wfUYq.js → erDiagram-2YWLMYGG-CNcqsnqx.js} +1 -1
- package/web/assets/{flowDiagram-T62WH6J4-BS-_wkGe.js → flowDiagram-T62WH6J4-pomAqjgF.js} +1 -1
- package/web/assets/{ganttDiagram-EL5Y4UJY-D9PWmuWE.js → ganttDiagram-EL5Y4UJY-C1dNaxxj.js} +1 -1
- package/web/assets/{gitGraphDiagram-WWUBYQGX-DIP9p63c.js → gitGraphDiagram-WWUBYQGX-Ni8GECg1.js} +1 -1
- package/web/assets/{infoDiagram-FKFFQAWI-BzU6-acC.js → infoDiagram-FKFFQAWI-C0kvE7Zu.js} +1 -1
- package/web/assets/{ishikawaDiagram-5VMMS53U-CvYS2ayc.js → ishikawaDiagram-5VMMS53U-CxmP_irp.js} +1 -1
- package/web/assets/{journeyDiagram-EYS64GPL-Cr0qdK-D.js → journeyDiagram-EYS64GPL-60GkPgH5.js} +1 -1
- package/web/assets/{kanban-definition-UXKFOSKX-DhffGp7U.js → kanban-definition-UXKFOSKX-ByxcB0T_.js} +1 -1
- package/web/assets/{layout-b5jqOIam.js → layout-BD9ef90s.js} +1 -1
- package/web/assets/{linear-zLNMwGhI.js → linear-Dp9l0lBr.js} +1 -1
- package/web/assets/{mermaid.core-DB_TNiSG.js → mermaid.core-FKm3Akes.js} +6 -6
- package/web/assets/{mindmap-definition-THT77NOG-DkQz2hbh.js → mindmap-definition-THT77NOG-i7WJlWHV.js} +1 -1
- package/web/assets/{pegDiagram-XKGWAZYB-CB313CDF.js → pegDiagram-XKGWAZYB-DfI-LsJq.js} +1 -1
- package/web/assets/{pieDiagram-E7YTZNPT-yaDJVY4d.js → pieDiagram-E7YTZNPT-kcgWYBSb.js} +1 -1
- package/web/assets/{quadrantDiagram-AXDQQJYC-BkV8iwHS.js → quadrantDiagram-AXDQQJYC-DVyziZnc.js} +1 -1
- package/web/assets/{railroadDiagram-O6MQD6OU-T_JVDRpV.js → railroadDiagram-O6MQD6OU-CWgHq9nv.js} +1 -1
- package/web/assets/{requirementDiagram-IS5BZ75X-B68yTCqr.js → requirementDiagram-IS5BZ75X-B7fgi4lz.js} +1 -1
- package/web/assets/{sankeyDiagram-P5KCCOFB-Bx31O26O.js → sankeyDiagram-P5KCCOFB-D1-pD_qh.js} +1 -1
- package/web/assets/{sequenceDiagram-WJ2MYXX4-CsCoFTAg.js → sequenceDiagram-WJ2MYXX4-B6oeRmVj.js} +1 -1
- package/web/assets/{sizeCapture-INFHLROL-B3a49hkJ.js → sizeCapture-INFHLROL-BTpKGFt5.js} +1 -1
- package/web/assets/{stateDiagram-XQSTLZYL-DjCdHmx5.js → stateDiagram-XQSTLZYL-zXJRxE6h.js} +1 -1
- package/web/assets/stateDiagram-v2-IH3M54BS-CmwZ6tXj.js +1 -0
- package/web/assets/{swimlanes-V6O3JKXN-4u8S1I3e.js → swimlanes-V6O3JKXN-Dc7MXPb3.js} +1 -1
- package/web/assets/swimlanesDiagram-JKAHXJPX-BXoJEx2b.js +8 -0
- package/web/assets/{timeline-definition-24CTP7MA-r3GnOjJo.js → timeline-definition-24CTP7MA-DYhgbnjW.js} +1 -1
- package/web/assets/{vennDiagram-4TSXK5OY-59IlTU54.js → vennDiagram-4TSXK5OY-DRnme7za.js} +1 -1
- package/web/assets/{wardleyDiagram-VM6X3IG4-C3ALfLHE.js → wardleyDiagram-VM6X3IG4-wAoo4GsZ.js} +1 -1
- package/web/assets/{workspace-file-tree-C6GhNx3L.js → workspace-file-tree-DmAwvqtx.js} +1 -1
- package/web/assets/{xychartDiagram-S5SC5T6Z-CoYtWlkb.js → xychartDiagram-S5SC5T6Z-_Z_TOWBn.js} +1 -1
- package/web/index.html +2 -2
- package/web/assets/app-DVblmMbF.css +0 -32
- package/web/assets/channel-DwV664-P.js +0 -1
- package/web/assets/classDiagram-CYGNFDIV-BKhd9faI.js +0 -1
- package/web/assets/classDiagram-v2-TLXNO2FR-BKhd9faI.js +0 -1
- package/web/assets/stateDiagram-v2-IH3M54BS-Cf0tqY7x.js +0 -1
- package/web/assets/swimlanesDiagram-JKAHXJPX-COK5qx0u.js +0 -8
|
@@ -13739,6 +13739,138 @@ function hasGatewayUsageLimitHttpMarker(response) {
|
|
|
13739
13739
|
return response.status === 429 && response.headers.get("X-OpenWork-Error-Code") === GATEWAY_USAGE_LIMIT_ERROR_CODE && response.headers.get("X-OpenWork-Usage-State") === "blocked";
|
|
13740
13740
|
}
|
|
13741
13741
|
|
|
13742
|
+
// ../../packages/types/src/den/inference.ts
|
|
13743
|
+
var INFERENCE_WINDOW_DURATIONS_MS = {
|
|
13744
|
+
five_hour: 5 * 60 * 60 * 1000,
|
|
13745
|
+
weekly: 7 * 24 * 60 * 60 * 1000,
|
|
13746
|
+
monthly: 30 * 24 * 60 * 60 * 1000
|
|
13747
|
+
};
|
|
13748
|
+
var OPENWORK_MODELS_ALLOWANCE_ERROR_CODE = "openwork_models_allowance_reached";
|
|
13749
|
+
var OPENWORK_MODELS_ALLOWANCE_SOURCE = "openwork_models";
|
|
13750
|
+
var OPENWORK_MODELS_ALLOWANCE_MESSAGE = "Your workspace used its OpenWork Models allowance.";
|
|
13751
|
+
function openWorkModelsAllowanceErrorBody() {
|
|
13752
|
+
return {
|
|
13753
|
+
error: {
|
|
13754
|
+
message: OPENWORK_MODELS_ALLOWANCE_MESSAGE,
|
|
13755
|
+
type: "usage_limit_error",
|
|
13756
|
+
param: null,
|
|
13757
|
+
code: OPENWORK_MODELS_ALLOWANCE_ERROR_CODE,
|
|
13758
|
+
source: OPENWORK_MODELS_ALLOWANCE_SOURCE
|
|
13759
|
+
}
|
|
13760
|
+
};
|
|
13761
|
+
}
|
|
13762
|
+
function hasOpenWorkModelsAllowanceHttpMarker(response) {
|
|
13763
|
+
return response.status === 429 && response.headers.get("X-OpenWork-Error-Code") === OPENWORK_MODELS_ALLOWANCE_ERROR_CODE && response.headers.get("X-OpenWork-Usage-State") === "blocked";
|
|
13764
|
+
}
|
|
13765
|
+
var INFERENCE_ACCESS_REASONS = [
|
|
13766
|
+
"admin_disabled",
|
|
13767
|
+
"not_eligible",
|
|
13768
|
+
"free_disabled",
|
|
13769
|
+
"accounting_unavailable",
|
|
13770
|
+
"free_allowance_exhausted",
|
|
13771
|
+
"upstream_unavailable"
|
|
13772
|
+
];
|
|
13773
|
+
var freeInferenceProviderSummarySchema = exports_external.object({
|
|
13774
|
+
state: exports_external.enum(["available", "disabled", "unavailable"]),
|
|
13775
|
+
reason: exports_external.union([exports_external.enum(INFERENCE_ACCESS_REASONS), exports_external.null()]),
|
|
13776
|
+
defaultPinned: exports_external.boolean(),
|
|
13777
|
+
modelGroup: exports_external.object({ id: exports_external.literal("free"), name: exports_external.literal("Free") }),
|
|
13778
|
+
catalog: exports_external.array(exports_external.object({ modelID: exports_external.string(), displayName: exports_external.string(), providerName: exports_external.string(), summary: exports_external.string(), recommended: exports_external.boolean(), rank: exports_external.number(), capabilities: exports_external.array(exports_external.string()) })),
|
|
13779
|
+
allowance: exports_external.object({
|
|
13780
|
+
usageScope: exports_external.literal("organization"),
|
|
13781
|
+
allowanceScope: exports_external.literal("person"),
|
|
13782
|
+
windowStartAt: exports_external.string().datetime(),
|
|
13783
|
+
resetsAt: exports_external.string().datetime(),
|
|
13784
|
+
weeklyLimitUsd: exports_external.number().finite().nonnegative(),
|
|
13785
|
+
joinedMembers: exports_external.number().int().nonnegative(),
|
|
13786
|
+
eligibleMembers: exports_external.number().int().nonnegative(),
|
|
13787
|
+
exhaustedMembers: exports_external.number().int().nonnegative().nullable().describe("Current eligible members whose recorded weekly usage has reached their person-wide limit; not a probe of Gateway request headroom. Null when accounting cannot be verified."),
|
|
13788
|
+
usedUsd: exports_external.number().finite().nonnegative().nullable(),
|
|
13789
|
+
requestCount: exports_external.number().int().nonnegative().nullable()
|
|
13790
|
+
})
|
|
13791
|
+
});
|
|
13792
|
+
var inferenceApiKeyMapSecretSchema = exports_external.record(exports_external.string(), exports_external.string()).refine((value) => Object.keys(value).length > 0, {
|
|
13793
|
+
message: "api_key_map must contain at least one entry"
|
|
13794
|
+
});
|
|
13795
|
+
var inferenceAwsKeysSecretSchema = exports_external.object({
|
|
13796
|
+
accessKeyId: exports_external.string().min(1),
|
|
13797
|
+
secretAccessKey: exports_external.string().min(1),
|
|
13798
|
+
sessionToken: exports_external.string().min(1).optional(),
|
|
13799
|
+
region: exports_external.string().min(1).optional()
|
|
13800
|
+
});
|
|
13801
|
+
var inferenceGcpServiceAccountSecretSchema = exports_external.looseObject({
|
|
13802
|
+
client_email: exports_external.string().min(1),
|
|
13803
|
+
private_key: exports_external.string().min(1),
|
|
13804
|
+
token_uri: exports_external.string().min(1)
|
|
13805
|
+
});
|
|
13806
|
+
var authorizationRevisionSchema = exports_external.string().regex(/^[A-Za-z0-9_-]{43}$/);
|
|
13807
|
+
var microsoftTenantIdSchema = exports_external.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
|
|
13808
|
+
var inferenceOauthTokenSecretSchema = exports_external.object({
|
|
13809
|
+
accessToken: exports_external.string().min(1),
|
|
13810
|
+
refreshToken: exports_external.string().min(1).optional(),
|
|
13811
|
+
tokenType: exports_external.string().min(1).optional(),
|
|
13812
|
+
googleIdentity: exports_external.object({
|
|
13813
|
+
subject: exports_external.string().min(1).max(255),
|
|
13814
|
+
email: exports_external.email(),
|
|
13815
|
+
emailVerified: exports_external.literal(true),
|
|
13816
|
+
clientId: exports_external.string().min(1),
|
|
13817
|
+
authorizationRevision: authorizationRevisionSchema.optional()
|
|
13818
|
+
}).optional(),
|
|
13819
|
+
microsoftIdentity: exports_external.object({
|
|
13820
|
+
tenantId: microsoftTenantIdSchema,
|
|
13821
|
+
objectId: exports_external.string().min(1).max(255),
|
|
13822
|
+
userName: exports_external.string().min(1).max(320).nullable(),
|
|
13823
|
+
clientId: exports_external.string().min(1),
|
|
13824
|
+
authorizationRevision: authorizationRevisionSchema
|
|
13825
|
+
}).optional()
|
|
13826
|
+
});
|
|
13827
|
+
var awsAccountIdSchema = exports_external.string().regex(/^\d{12}$/);
|
|
13828
|
+
var awsPermissionSetNameSchema = exports_external.string().regex(/^[\w+=,.@-]{1,32}$/);
|
|
13829
|
+
var awsSsoStartUrlSchema = exports_external.string().max(2048).refine((value) => {
|
|
13830
|
+
try {
|
|
13831
|
+
const url2 = new URL(value);
|
|
13832
|
+
return url2.protocol === "https:" && !url2.username && !url2.password && !url2.search && !url2.hash && !url2.port && /^[a-z0-9-]+(?:\.[a-z0-9-]+)*\.(?:awsapps\.com|app\.aws)$/i.test(url2.hostname);
|
|
13833
|
+
} catch {
|
|
13834
|
+
return false;
|
|
13835
|
+
}
|
|
13836
|
+
}, { message: "Use the AWS access portal URL, for example https://d-xxxxxxxxxx.awsapps.com/start." });
|
|
13837
|
+
var awsRegionSchema = exports_external.string().max(32).regex(/^[a-z]{2}(?:-[a-z]+)+-\d{1,2}$/);
|
|
13838
|
+
var gatewayAwsSsoSettingsSchema = exports_external.object({
|
|
13839
|
+
startUrl: awsSsoStartUrlSchema,
|
|
13840
|
+
region: awsRegionSchema,
|
|
13841
|
+
accountId: awsAccountIdSchema,
|
|
13842
|
+
roleName: awsPermissionSetNameSchema
|
|
13843
|
+
}).strict();
|
|
13844
|
+
var inferenceAwsSsoSecretSchema = exports_external.object({
|
|
13845
|
+
accessToken: exports_external.string().min(1).max(16384),
|
|
13846
|
+
refreshToken: exports_external.string().min(1).max(16384),
|
|
13847
|
+
clientId: exports_external.string().min(1).max(4096),
|
|
13848
|
+
clientSecret: exports_external.string().min(1).max(16384),
|
|
13849
|
+
clientSecretExpiresAt: exports_external.number().int().positive(),
|
|
13850
|
+
sso: gatewayAwsSsoSettingsSchema,
|
|
13851
|
+
identity: exports_external.object({
|
|
13852
|
+
arn: exports_external.string().min(1).max(2048),
|
|
13853
|
+
userName: exports_external.string().min(1).max(320).nullable(),
|
|
13854
|
+
authorizationRevision: authorizationRevisionSchema
|
|
13855
|
+
})
|
|
13856
|
+
});
|
|
13857
|
+
var GATEWAY_MEMBER_SIGN_IN_METHODS = ["google", "aws_sso", "microsoft"];
|
|
13858
|
+
var gatewayMemberConnectionsResponseSchema = exports_external.object({
|
|
13859
|
+
connections: exports_external.array(exports_external.object({
|
|
13860
|
+
providerId: exports_external.string(),
|
|
13861
|
+
signInMethod: exports_external.enum(GATEWAY_MEMBER_SIGN_IN_METHODS).default("google"),
|
|
13862
|
+
credentialSetId: exports_external.string(),
|
|
13863
|
+
providerName: exports_external.string(),
|
|
13864
|
+
name: exports_external.string(),
|
|
13865
|
+
ready: exports_external.boolean(),
|
|
13866
|
+
hasAccess: exports_external.boolean(),
|
|
13867
|
+
hasCredential: exports_external.boolean(),
|
|
13868
|
+
configurationRequired: exports_external.boolean().default(false),
|
|
13869
|
+
authorizationRevision: exports_external.string().nullable(),
|
|
13870
|
+
accountEmail: exports_external.string().nullable()
|
|
13871
|
+
}))
|
|
13872
|
+
});
|
|
13873
|
+
|
|
13742
13874
|
// src/gateway-quota.ts
|
|
13743
13875
|
var GATEWAY_QUOTA_MESSAGE = "You have reached your AI Gateway usage limit.";
|
|
13744
13876
|
var MAX_ERROR_BYTES = 16384;
|
|
@@ -13761,6 +13893,61 @@ function gatewayBase(id, baseURL) {
|
|
|
13761
13893
|
return;
|
|
13762
13894
|
}
|
|
13763
13895
|
}
|
|
13896
|
+
function openWorkModelsBase(id, baseURL) {
|
|
13897
|
+
if (id !== "openwork" || typeof baseURL !== "string")
|
|
13898
|
+
return;
|
|
13899
|
+
try {
|
|
13900
|
+
const url2 = new URL(baseURL);
|
|
13901
|
+
if (!["https:", "http:"].includes(url2.protocol) || url2.username || url2.password || url2.search || url2.hash)
|
|
13902
|
+
return;
|
|
13903
|
+
url2.pathname = url2.pathname.replace(/\/+$/, "");
|
|
13904
|
+
if (!url2.pathname.endsWith("/api/v1"))
|
|
13905
|
+
return;
|
|
13906
|
+
return url2;
|
|
13907
|
+
} catch {
|
|
13908
|
+
return;
|
|
13909
|
+
}
|
|
13910
|
+
}
|
|
13911
|
+
async function isOpenWorkModelsAllowanceResponse(base, url2, response) {
|
|
13912
|
+
if (url2.origin !== base.origin || !url2.pathname.startsWith(`${base.pathname}/`) || response.url && new URL(response.url).origin !== base.origin || !hasOpenWorkModelsAllowanceHttpMarker(response))
|
|
13913
|
+
return false;
|
|
13914
|
+
const body = await readBoundedJson(response);
|
|
13915
|
+
return record2(body) && record2(body.error) && body.error.code === OPENWORK_MODELS_ALLOWANCE_ERROR_CODE && body.error.source === OPENWORK_MODELS_ALLOWANCE_SOURCE;
|
|
13916
|
+
}
|
|
13917
|
+
async function readBoundedJson(response) {
|
|
13918
|
+
const reader = response.clone().body?.getReader();
|
|
13919
|
+
if (!reader)
|
|
13920
|
+
return null;
|
|
13921
|
+
let timer;
|
|
13922
|
+
const expired = new Promise((resolve) => {
|
|
13923
|
+
timer = setTimeout(() => resolve(null), BODY_TIMEOUT_MS);
|
|
13924
|
+
});
|
|
13925
|
+
const read = async () => {
|
|
13926
|
+
let size = 0;
|
|
13927
|
+
let text = "";
|
|
13928
|
+
const decoder = new TextDecoder;
|
|
13929
|
+
while (true) {
|
|
13930
|
+
const chunk = await reader.read();
|
|
13931
|
+
if (chunk.done)
|
|
13932
|
+
break;
|
|
13933
|
+
size += chunk.value.byteLength;
|
|
13934
|
+
if (size > MAX_ERROR_BYTES)
|
|
13935
|
+
return null;
|
|
13936
|
+
text += decoder.decode(chunk.value, { stream: true });
|
|
13937
|
+
}
|
|
13938
|
+
return JSON.parse(text + decoder.decode());
|
|
13939
|
+
};
|
|
13940
|
+
try {
|
|
13941
|
+
return await Promise.race([read(), expired]);
|
|
13942
|
+
} catch {
|
|
13943
|
+
return null;
|
|
13944
|
+
} finally {
|
|
13945
|
+
clearTimeout(timer);
|
|
13946
|
+
reader.cancel().catch(() => {
|
|
13947
|
+
return;
|
|
13948
|
+
});
|
|
13949
|
+
}
|
|
13950
|
+
}
|
|
13764
13951
|
async function isGatewayQuotaResponse(base, url2, response) {
|
|
13765
13952
|
if (url2.origin !== base.origin || !url2.pathname.startsWith(`${base.pathname}/`) || response.url && new URL(response.url).origin !== base.origin || !hasGatewayUsageLimitHttpMarker(response))
|
|
13766
13953
|
return false;
|
|
@@ -14053,6 +14053,138 @@ function hasGatewayUsageLimitHttpMarker(response) {
|
|
|
14053
14053
|
return response.status === 429 && response.headers.get("X-OpenWork-Error-Code") === GATEWAY_USAGE_LIMIT_ERROR_CODE && response.headers.get("X-OpenWork-Usage-State") === "blocked";
|
|
14054
14054
|
}
|
|
14055
14055
|
|
|
14056
|
+
// ../../packages/types/src/den/inference.ts
|
|
14057
|
+
var INFERENCE_WINDOW_DURATIONS_MS = {
|
|
14058
|
+
five_hour: 5 * 60 * 60 * 1000,
|
|
14059
|
+
weekly: 7 * 24 * 60 * 60 * 1000,
|
|
14060
|
+
monthly: 30 * 24 * 60 * 60 * 1000
|
|
14061
|
+
};
|
|
14062
|
+
var OPENWORK_MODELS_ALLOWANCE_ERROR_CODE = "openwork_models_allowance_reached";
|
|
14063
|
+
var OPENWORK_MODELS_ALLOWANCE_SOURCE = "openwork_models";
|
|
14064
|
+
var OPENWORK_MODELS_ALLOWANCE_MESSAGE = "Your workspace used its OpenWork Models allowance.";
|
|
14065
|
+
function openWorkModelsAllowanceErrorBody() {
|
|
14066
|
+
return {
|
|
14067
|
+
error: {
|
|
14068
|
+
message: OPENWORK_MODELS_ALLOWANCE_MESSAGE,
|
|
14069
|
+
type: "usage_limit_error",
|
|
14070
|
+
param: null,
|
|
14071
|
+
code: OPENWORK_MODELS_ALLOWANCE_ERROR_CODE,
|
|
14072
|
+
source: OPENWORK_MODELS_ALLOWANCE_SOURCE
|
|
14073
|
+
}
|
|
14074
|
+
};
|
|
14075
|
+
}
|
|
14076
|
+
function hasOpenWorkModelsAllowanceHttpMarker(response) {
|
|
14077
|
+
return response.status === 429 && response.headers.get("X-OpenWork-Error-Code") === OPENWORK_MODELS_ALLOWANCE_ERROR_CODE && response.headers.get("X-OpenWork-Usage-State") === "blocked";
|
|
14078
|
+
}
|
|
14079
|
+
var INFERENCE_ACCESS_REASONS = [
|
|
14080
|
+
"admin_disabled",
|
|
14081
|
+
"not_eligible",
|
|
14082
|
+
"free_disabled",
|
|
14083
|
+
"accounting_unavailable",
|
|
14084
|
+
"free_allowance_exhausted",
|
|
14085
|
+
"upstream_unavailable"
|
|
14086
|
+
];
|
|
14087
|
+
var freeInferenceProviderSummarySchema = exports_external.object({
|
|
14088
|
+
state: exports_external.enum(["available", "disabled", "unavailable"]),
|
|
14089
|
+
reason: exports_external.union([exports_external.enum(INFERENCE_ACCESS_REASONS), exports_external.null()]),
|
|
14090
|
+
defaultPinned: exports_external.boolean(),
|
|
14091
|
+
modelGroup: exports_external.object({ id: exports_external.literal("free"), name: exports_external.literal("Free") }),
|
|
14092
|
+
catalog: exports_external.array(exports_external.object({ modelID: exports_external.string(), displayName: exports_external.string(), providerName: exports_external.string(), summary: exports_external.string(), recommended: exports_external.boolean(), rank: exports_external.number(), capabilities: exports_external.array(exports_external.string()) })),
|
|
14093
|
+
allowance: exports_external.object({
|
|
14094
|
+
usageScope: exports_external.literal("organization"),
|
|
14095
|
+
allowanceScope: exports_external.literal("person"),
|
|
14096
|
+
windowStartAt: exports_external.string().datetime(),
|
|
14097
|
+
resetsAt: exports_external.string().datetime(),
|
|
14098
|
+
weeklyLimitUsd: exports_external.number().finite().nonnegative(),
|
|
14099
|
+
joinedMembers: exports_external.number().int().nonnegative(),
|
|
14100
|
+
eligibleMembers: exports_external.number().int().nonnegative(),
|
|
14101
|
+
exhaustedMembers: exports_external.number().int().nonnegative().nullable().describe("Current eligible members whose recorded weekly usage has reached their person-wide limit; not a probe of Gateway request headroom. Null when accounting cannot be verified."),
|
|
14102
|
+
usedUsd: exports_external.number().finite().nonnegative().nullable(),
|
|
14103
|
+
requestCount: exports_external.number().int().nonnegative().nullable()
|
|
14104
|
+
})
|
|
14105
|
+
});
|
|
14106
|
+
var inferenceApiKeyMapSecretSchema = exports_external.record(exports_external.string(), exports_external.string()).refine((value) => Object.keys(value).length > 0, {
|
|
14107
|
+
message: "api_key_map must contain at least one entry"
|
|
14108
|
+
});
|
|
14109
|
+
var inferenceAwsKeysSecretSchema = exports_external.object({
|
|
14110
|
+
accessKeyId: exports_external.string().min(1),
|
|
14111
|
+
secretAccessKey: exports_external.string().min(1),
|
|
14112
|
+
sessionToken: exports_external.string().min(1).optional(),
|
|
14113
|
+
region: exports_external.string().min(1).optional()
|
|
14114
|
+
});
|
|
14115
|
+
var inferenceGcpServiceAccountSecretSchema = exports_external.looseObject({
|
|
14116
|
+
client_email: exports_external.string().min(1),
|
|
14117
|
+
private_key: exports_external.string().min(1),
|
|
14118
|
+
token_uri: exports_external.string().min(1)
|
|
14119
|
+
});
|
|
14120
|
+
var authorizationRevisionSchema = exports_external.string().regex(/^[A-Za-z0-9_-]{43}$/);
|
|
14121
|
+
var microsoftTenantIdSchema = exports_external.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
|
|
14122
|
+
var inferenceOauthTokenSecretSchema = exports_external.object({
|
|
14123
|
+
accessToken: exports_external.string().min(1),
|
|
14124
|
+
refreshToken: exports_external.string().min(1).optional(),
|
|
14125
|
+
tokenType: exports_external.string().min(1).optional(),
|
|
14126
|
+
googleIdentity: exports_external.object({
|
|
14127
|
+
subject: exports_external.string().min(1).max(255),
|
|
14128
|
+
email: exports_external.email(),
|
|
14129
|
+
emailVerified: exports_external.literal(true),
|
|
14130
|
+
clientId: exports_external.string().min(1),
|
|
14131
|
+
authorizationRevision: authorizationRevisionSchema.optional()
|
|
14132
|
+
}).optional(),
|
|
14133
|
+
microsoftIdentity: exports_external.object({
|
|
14134
|
+
tenantId: microsoftTenantIdSchema,
|
|
14135
|
+
objectId: exports_external.string().min(1).max(255),
|
|
14136
|
+
userName: exports_external.string().min(1).max(320).nullable(),
|
|
14137
|
+
clientId: exports_external.string().min(1),
|
|
14138
|
+
authorizationRevision: authorizationRevisionSchema
|
|
14139
|
+
}).optional()
|
|
14140
|
+
});
|
|
14141
|
+
var awsAccountIdSchema = exports_external.string().regex(/^\d{12}$/);
|
|
14142
|
+
var awsPermissionSetNameSchema = exports_external.string().regex(/^[\w+=,.@-]{1,32}$/);
|
|
14143
|
+
var awsSsoStartUrlSchema = exports_external.string().max(2048).refine((value) => {
|
|
14144
|
+
try {
|
|
14145
|
+
const url2 = new URL(value);
|
|
14146
|
+
return url2.protocol === "https:" && !url2.username && !url2.password && !url2.search && !url2.hash && !url2.port && /^[a-z0-9-]+(?:\.[a-z0-9-]+)*\.(?:awsapps\.com|app\.aws)$/i.test(url2.hostname);
|
|
14147
|
+
} catch {
|
|
14148
|
+
return false;
|
|
14149
|
+
}
|
|
14150
|
+
}, { message: "Use the AWS access portal URL, for example https://d-xxxxxxxxxx.awsapps.com/start." });
|
|
14151
|
+
var awsRegionSchema = exports_external.string().max(32).regex(/^[a-z]{2}(?:-[a-z]+)+-\d{1,2}$/);
|
|
14152
|
+
var gatewayAwsSsoSettingsSchema = exports_external.object({
|
|
14153
|
+
startUrl: awsSsoStartUrlSchema,
|
|
14154
|
+
region: awsRegionSchema,
|
|
14155
|
+
accountId: awsAccountIdSchema,
|
|
14156
|
+
roleName: awsPermissionSetNameSchema
|
|
14157
|
+
}).strict();
|
|
14158
|
+
var inferenceAwsSsoSecretSchema = exports_external.object({
|
|
14159
|
+
accessToken: exports_external.string().min(1).max(16384),
|
|
14160
|
+
refreshToken: exports_external.string().min(1).max(16384),
|
|
14161
|
+
clientId: exports_external.string().min(1).max(4096),
|
|
14162
|
+
clientSecret: exports_external.string().min(1).max(16384),
|
|
14163
|
+
clientSecretExpiresAt: exports_external.number().int().positive(),
|
|
14164
|
+
sso: gatewayAwsSsoSettingsSchema,
|
|
14165
|
+
identity: exports_external.object({
|
|
14166
|
+
arn: exports_external.string().min(1).max(2048),
|
|
14167
|
+
userName: exports_external.string().min(1).max(320).nullable(),
|
|
14168
|
+
authorizationRevision: authorizationRevisionSchema
|
|
14169
|
+
})
|
|
14170
|
+
});
|
|
14171
|
+
var GATEWAY_MEMBER_SIGN_IN_METHODS = ["google", "aws_sso", "microsoft"];
|
|
14172
|
+
var gatewayMemberConnectionsResponseSchema = exports_external.object({
|
|
14173
|
+
connections: exports_external.array(exports_external.object({
|
|
14174
|
+
providerId: exports_external.string(),
|
|
14175
|
+
signInMethod: exports_external.enum(GATEWAY_MEMBER_SIGN_IN_METHODS).default("google"),
|
|
14176
|
+
credentialSetId: exports_external.string(),
|
|
14177
|
+
providerName: exports_external.string(),
|
|
14178
|
+
name: exports_external.string(),
|
|
14179
|
+
ready: exports_external.boolean(),
|
|
14180
|
+
hasAccess: exports_external.boolean(),
|
|
14181
|
+
hasCredential: exports_external.boolean(),
|
|
14182
|
+
configurationRequired: exports_external.boolean().default(false),
|
|
14183
|
+
authorizationRevision: exports_external.string().nullable(),
|
|
14184
|
+
accountEmail: exports_external.string().nullable()
|
|
14185
|
+
}))
|
|
14186
|
+
});
|
|
14187
|
+
|
|
14056
14188
|
// src/gateway-quota.ts
|
|
14057
14189
|
var GATEWAY_QUOTA_MESSAGE = "You have reached your AI Gateway usage limit.";
|
|
14058
14190
|
var MAX_ERROR_BYTES = 16384;
|
|
@@ -14075,6 +14207,61 @@ function gatewayBase(id, baseURL) {
|
|
|
14075
14207
|
return;
|
|
14076
14208
|
}
|
|
14077
14209
|
}
|
|
14210
|
+
function openWorkModelsBase(id, baseURL) {
|
|
14211
|
+
if (id !== "openwork" || typeof baseURL !== "string")
|
|
14212
|
+
return;
|
|
14213
|
+
try {
|
|
14214
|
+
const url2 = new URL(baseURL);
|
|
14215
|
+
if (!["https:", "http:"].includes(url2.protocol) || url2.username || url2.password || url2.search || url2.hash)
|
|
14216
|
+
return;
|
|
14217
|
+
url2.pathname = url2.pathname.replace(/\/+$/, "");
|
|
14218
|
+
if (!url2.pathname.endsWith("/api/v1"))
|
|
14219
|
+
return;
|
|
14220
|
+
return url2;
|
|
14221
|
+
} catch {
|
|
14222
|
+
return;
|
|
14223
|
+
}
|
|
14224
|
+
}
|
|
14225
|
+
async function isOpenWorkModelsAllowanceResponse(base, url2, response) {
|
|
14226
|
+
if (url2.origin !== base.origin || !url2.pathname.startsWith(`${base.pathname}/`) || response.url && new URL(response.url).origin !== base.origin || !hasOpenWorkModelsAllowanceHttpMarker(response))
|
|
14227
|
+
return false;
|
|
14228
|
+
const body = await readBoundedJson(response);
|
|
14229
|
+
return record2(body) && record2(body.error) && body.error.code === OPENWORK_MODELS_ALLOWANCE_ERROR_CODE && body.error.source === OPENWORK_MODELS_ALLOWANCE_SOURCE;
|
|
14230
|
+
}
|
|
14231
|
+
async function readBoundedJson(response) {
|
|
14232
|
+
const reader = response.clone().body?.getReader();
|
|
14233
|
+
if (!reader)
|
|
14234
|
+
return null;
|
|
14235
|
+
let timer;
|
|
14236
|
+
const expired = new Promise((resolve) => {
|
|
14237
|
+
timer = setTimeout(() => resolve(null), BODY_TIMEOUT_MS);
|
|
14238
|
+
});
|
|
14239
|
+
const read = async () => {
|
|
14240
|
+
let size = 0;
|
|
14241
|
+
let text = "";
|
|
14242
|
+
const decoder = new TextDecoder;
|
|
14243
|
+
while (true) {
|
|
14244
|
+
const chunk = await reader.read();
|
|
14245
|
+
if (chunk.done)
|
|
14246
|
+
break;
|
|
14247
|
+
size += chunk.value.byteLength;
|
|
14248
|
+
if (size > MAX_ERROR_BYTES)
|
|
14249
|
+
return null;
|
|
14250
|
+
text += decoder.decode(chunk.value, { stream: true });
|
|
14251
|
+
}
|
|
14252
|
+
return JSON.parse(text + decoder.decode());
|
|
14253
|
+
};
|
|
14254
|
+
try {
|
|
14255
|
+
return await Promise.race([read(), expired]);
|
|
14256
|
+
} catch {
|
|
14257
|
+
return null;
|
|
14258
|
+
} finally {
|
|
14259
|
+
clearTimeout(timer);
|
|
14260
|
+
reader.cancel().catch(() => {
|
|
14261
|
+
return;
|
|
14262
|
+
});
|
|
14263
|
+
}
|
|
14264
|
+
}
|
|
14078
14265
|
async function isGatewayQuotaResponse(base, url2, response) {
|
|
14079
14266
|
if (url2.origin !== base.origin || !url2.pathname.startsWith(`${base.pathname}/`) || response.url && new URL(response.url).origin !== base.origin || !hasGatewayUsageLimitHttpMarker(response))
|
|
14080
14267
|
return false;
|
|
@@ -14114,38 +14301,60 @@ async function isGatewayQuotaResponse(base, url2, response) {
|
|
|
14114
14301
|
}
|
|
14115
14302
|
|
|
14116
14303
|
// src/opencode-plugins/openwork-gateway-quota.ts
|
|
14304
|
+
function noRetryFetch(base, matches, error48) {
|
|
14305
|
+
return async (input, init) => {
|
|
14306
|
+
const response = await globalThis.fetch(input, init);
|
|
14307
|
+
const url2 = new URL(input instanceof Request ? input.url : input.toString());
|
|
14308
|
+
if (!await matches(base, url2, response))
|
|
14309
|
+
return response;
|
|
14310
|
+
response.body?.cancel().catch(() => {
|
|
14311
|
+
return;
|
|
14312
|
+
});
|
|
14313
|
+
throw error48(url2, response);
|
|
14314
|
+
};
|
|
14315
|
+
}
|
|
14117
14316
|
var OpenWorkGatewayQuota = async () => ({
|
|
14118
14317
|
config: async (config2) => {
|
|
14119
14318
|
for (const [id, provider] of Object.entries(config2.provider ?? {})) {
|
|
14120
|
-
if (!record2(provider)
|
|
14121
|
-
continue;
|
|
14122
|
-
const options = provider.options;
|
|
14123
|
-
const base = gatewayBase(id, options.baseURL);
|
|
14124
|
-
if (!base || options.fetch !== undefined)
|
|
14319
|
+
if (!record2(provider))
|
|
14125
14320
|
continue;
|
|
14126
|
-
|
|
14127
|
-
|
|
14128
|
-
const
|
|
14129
|
-
if (
|
|
14130
|
-
|
|
14131
|
-
|
|
14132
|
-
|
|
14133
|
-
});
|
|
14134
|
-
throw new APICallError({
|
|
14135
|
-
message: GATEWAY_QUOTA_MESSAGE,
|
|
14321
|
+
const models = openWorkModelsBase(id, record2(provider.options) ? provider.options.baseURL ?? provider.api : provider.api);
|
|
14322
|
+
if (models) {
|
|
14323
|
+
const options2 = record2(provider.options) ? provider.options : {};
|
|
14324
|
+
if (options2.fetch !== undefined)
|
|
14325
|
+
continue;
|
|
14326
|
+
options2.fetch = noRetryFetch(models, isOpenWorkModelsAllowanceResponse, (url2, response) => new APICallError({
|
|
14327
|
+
message: OPENWORK_MODELS_ALLOWANCE_MESSAGE,
|
|
14136
14328
|
url: `${url2.origin}${url2.pathname}`,
|
|
14137
14329
|
requestBodyValues: undefined,
|
|
14138
14330
|
statusCode: response.status,
|
|
14139
14331
|
responseHeaders: Object.fromEntries(response.headers),
|
|
14140
|
-
responseBody: JSON.stringify(
|
|
14141
|
-
type: "usage_limit_error",
|
|
14142
|
-
code: GATEWAY_USAGE_LIMIT_ERROR_CODE,
|
|
14143
|
-
source: "openwork_gateway",
|
|
14144
|
-
message: GATEWAY_QUOTA_MESSAGE
|
|
14145
|
-
} }),
|
|
14332
|
+
responseBody: JSON.stringify(openWorkModelsAllowanceErrorBody()),
|
|
14146
14333
|
isRetryable: false
|
|
14147
|
-
});
|
|
14148
|
-
|
|
14334
|
+
}));
|
|
14335
|
+
provider.options = options2;
|
|
14336
|
+
continue;
|
|
14337
|
+
}
|
|
14338
|
+
if (!record2(provider.options))
|
|
14339
|
+
continue;
|
|
14340
|
+
const options = provider.options;
|
|
14341
|
+
const base = gatewayBase(id, options.baseURL);
|
|
14342
|
+
if (!base || options.fetch !== undefined)
|
|
14343
|
+
continue;
|
|
14344
|
+
options.fetch = noRetryFetch(base, isGatewayQuotaResponse, (url2, response) => new APICallError({
|
|
14345
|
+
message: GATEWAY_QUOTA_MESSAGE,
|
|
14346
|
+
url: `${url2.origin}${url2.pathname}`,
|
|
14347
|
+
requestBodyValues: undefined,
|
|
14348
|
+
statusCode: response.status,
|
|
14349
|
+
responseHeaders: Object.fromEntries(response.headers),
|
|
14350
|
+
responseBody: JSON.stringify({ error: {
|
|
14351
|
+
type: "usage_limit_error",
|
|
14352
|
+
code: GATEWAY_USAGE_LIMIT_ERROR_CODE,
|
|
14353
|
+
source: "openwork_gateway",
|
|
14354
|
+
message: GATEWAY_QUOTA_MESSAGE
|
|
14355
|
+
} }),
|
|
14356
|
+
isRetryable: false
|
|
14357
|
+
}));
|
|
14149
14358
|
}
|
|
14150
14359
|
}
|
|
14151
14360
|
});
|
|
@@ -2944,6 +2944,87 @@ function toProviderRecord(provider, apiKey) {
|
|
|
2944
2944
|
return { info, models };
|
|
2945
2945
|
}
|
|
2946
2946
|
|
|
2947
|
+
// ../../packages/opencode-plugin/src/inventory-fetch.ts
|
|
2948
|
+
function abortError(signal) {
|
|
2949
|
+
return signal.reason ?? new DOMException("The operation was aborted.", "AbortError");
|
|
2950
|
+
}
|
|
2951
|
+
function createInventoryFetchHub() {
|
|
2952
|
+
const shared = new Map;
|
|
2953
|
+
let sequence = 0;
|
|
2954
|
+
const ticket = () => ++sequence;
|
|
2955
|
+
const start = (key, request) => {
|
|
2956
|
+
const controller = new AbortController;
|
|
2957
|
+
const entry = {
|
|
2958
|
+
startedAfter: ++sequence,
|
|
2959
|
+
controller,
|
|
2960
|
+
joiners: 0,
|
|
2961
|
+
settled: false,
|
|
2962
|
+
result: fetchGatewayInventory(request.fetch, request.session, controller.signal, request.scope)
|
|
2963
|
+
};
|
|
2964
|
+
const settle = () => {
|
|
2965
|
+
entry.settled = true;
|
|
2966
|
+
if (shared.get(key) === entry)
|
|
2967
|
+
shared.delete(key);
|
|
2968
|
+
};
|
|
2969
|
+
entry.result.then(settle, settle);
|
|
2970
|
+
shared.set(key, entry);
|
|
2971
|
+
return entry;
|
|
2972
|
+
};
|
|
2973
|
+
const fetch2 = async (request) => {
|
|
2974
|
+
if (request.signal?.aborted)
|
|
2975
|
+
throw abortError(request.signal);
|
|
2976
|
+
const key = `${inventorySessionKey(request.session)}:${request.scope}`;
|
|
2977
|
+
const entry = shared.get(key);
|
|
2978
|
+
const current = entry && !entry.settled && entry.startedAfter > request.ticket ? entry : start(key, request);
|
|
2979
|
+
current.joiners += 1;
|
|
2980
|
+
const leave = () => {
|
|
2981
|
+
current.joiners -= 1;
|
|
2982
|
+
if (current.joiners === 0 && !current.settled)
|
|
2983
|
+
current.controller.abort();
|
|
2984
|
+
};
|
|
2985
|
+
const signal = request.signal;
|
|
2986
|
+
if (!signal) {
|
|
2987
|
+
try {
|
|
2988
|
+
return await current.result;
|
|
2989
|
+
} finally {
|
|
2990
|
+
leave();
|
|
2991
|
+
}
|
|
2992
|
+
}
|
|
2993
|
+
let onAbort;
|
|
2994
|
+
const aborted = new Promise((_, reject) => {
|
|
2995
|
+
onAbort = () => reject(abortError(signal));
|
|
2996
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
2997
|
+
});
|
|
2998
|
+
try {
|
|
2999
|
+
return await Promise.race([current.result, aborted]);
|
|
3000
|
+
} finally {
|
|
3001
|
+
if (onAbort)
|
|
3002
|
+
signal.removeEventListener("abort", onAbort);
|
|
3003
|
+
leave();
|
|
3004
|
+
}
|
|
3005
|
+
};
|
|
3006
|
+
return Object.freeze({ ticket: Object.freeze(ticket), fetch: Object.freeze(fetch2) });
|
|
3007
|
+
}
|
|
3008
|
+
function hub() {
|
|
3009
|
+
let current = globalThis.__openworkGatewayInventoryFetches;
|
|
3010
|
+
if (!current) {
|
|
3011
|
+
current = createInventoryFetchHub();
|
|
3012
|
+
Object.defineProperty(globalThis, "__openworkGatewayInventoryFetches", {
|
|
3013
|
+
value: current,
|
|
3014
|
+
writable: false,
|
|
3015
|
+
configurable: false,
|
|
3016
|
+
enumerable: false
|
|
3017
|
+
});
|
|
3018
|
+
}
|
|
3019
|
+
return current;
|
|
3020
|
+
}
|
|
3021
|
+
function inventoryRequestTicket() {
|
|
3022
|
+
return hub().ticket();
|
|
3023
|
+
}
|
|
3024
|
+
function fetchSharedGatewayInventory(request) {
|
|
3025
|
+
return hub().fetch(request);
|
|
3026
|
+
}
|
|
3027
|
+
|
|
2947
3028
|
// ../../packages/opencode-plugin/src/desktop.ts
|
|
2948
3029
|
var CACHE_KEY = "desktop/provider-inventory";
|
|
2949
3030
|
var digest = (value) => createHash2("sha256").update(JSON.stringify(value)).digest("hex");
|
|
@@ -3100,9 +3181,10 @@ function createDesktopProviderPlugin(deps = {}) {
|
|
|
3100
3181
|
const accountKey = key;
|
|
3101
3182
|
const generation = epoch;
|
|
3102
3183
|
const current = () => !lifetime.signal.aborted && generation === epoch;
|
|
3184
|
+
const ticket = inventoryRequestTicket();
|
|
3103
3185
|
running = (async () => {
|
|
3104
3186
|
try {
|
|
3105
|
-
const gateway = await
|
|
3187
|
+
const gateway = await fetchSharedGatewayInventory({ fetch: inventoryFetch(source), session: inventorySession(source), scope: "desktop", ticket, signal: refreshController.signal });
|
|
3106
3188
|
if (!current())
|
|
3107
3189
|
return;
|
|
3108
3190
|
const next = { version: 1, connectionKey: accountKey, apiBaseUrl: source.apiBaseUrl, fetchedAt: now(), gateway, mcp: null };
|
|
@@ -3662,6 +3744,7 @@ function createPlugin(deps = {}) {
|
|
|
3662
3744
|
});
|
|
3663
3745
|
};
|
|
3664
3746
|
const refreshOnce = async (force) => {
|
|
3747
|
+
const ticket = inventoryRequestTicket();
|
|
3665
3748
|
const epoch = generation;
|
|
3666
3749
|
const current = () => !disposed && epoch === generation;
|
|
3667
3750
|
const connection = await ctx.integration.connection.active(INTEGRATION_ID).catch(() => {
|
|
@@ -3744,7 +3827,7 @@ function createPlugin(deps = {}) {
|
|
|
3744
3827
|
return;
|
|
3745
3828
|
syncStream(session, liveProviderSync);
|
|
3746
3829
|
const [gateway, mcp] = await Promise.all([
|
|
3747
|
-
options.providers ?
|
|
3830
|
+
options.providers ? fetchSharedGatewayInventory({ fetch: fetcher, session, scope: "den", ticket, signal: refreshController.signal }).then((inventory2) => ({ providers: inventory2.providers, apiKey: inventory2.apiKey })) : Promise.resolve(null),
|
|
3748
3831
|
options.mcp ? (async () => {
|
|
3749
3832
|
const previous = sameAccount?.mcp?.token ?? null;
|
|
3750
3833
|
const token = previous && !mcpTokenNeedsRenewal(previous, now()) ? previous : await mintMcpToken(fetcher, session);
|