@integrity-labs/agt-cli 0.28.456 → 0.28.458
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/agt.js +4 -4
- package/dist/{chunk-UIUYOGPK.js → chunk-KAIH24HZ.js} +37 -4
- package/dist/chunk-KAIH24HZ.js.map +1 -0
- package/dist/{chunk-FNEUIWJJ.js → chunk-QIQQ46NH.js} +60 -22
- package/dist/{chunk-FNEUIWJJ.js.map → chunk-QIQQ46NH.js.map} +1 -1
- package/dist/{claude-pair-runtime-PHAR4IF4.js → claude-pair-runtime-CVCPBJOZ.js} +2 -2
- package/dist/lib/manager-worker.js +18 -11
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +22 -0
- package/dist/mcp/origami.js +245 -76
- package/dist/mcp/slack-channel.js +22 -0
- package/dist/mcp/telegram-channel.js +22 -0
- package/dist/{persistent-session-Z2UQ4VVF.js → persistent-session-EVLWDI3I.js} +2 -2
- package/dist/{responsiveness-probe-WCF2QEVT.js → responsiveness-probe-EGP2F3WD.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-UIUYOGPK.js.map +0 -1
- /package/dist/{claude-pair-runtime-PHAR4IF4.js.map → claude-pair-runtime-CVCPBJOZ.js.map} +0 -0
- /package/dist/{persistent-session-Z2UQ4VVF.js.map → persistent-session-EVLWDI3I.js.map} +0 -0
- /package/dist/{responsiveness-probe-WCF2QEVT.js.map → responsiveness-probe-EGP2F3WD.js.map} +0 -0
|
@@ -31704,6 +31704,12 @@ var integration_metadata_v1_default = {
|
|
|
31704
31704
|
description: "Optional query-string shape with `{arg}` placeholders.",
|
|
31705
31705
|
additionalProperties: { type: "string" }
|
|
31706
31706
|
},
|
|
31707
|
+
headers_template: {
|
|
31708
|
+
type: "object",
|
|
31709
|
+
description: 'Optional request-header shape with `{arg}` placeholders (e.g. `{ "x-origami-project": "{project_id}" }`). A header whose template resolves to empty is dropped rather than sent blank, and args consumed only by a header template are excluded from a `{$body}` expansion.',
|
|
31710
|
+
propertyNames: { pattern: "^[A-Za-z0-9!#$%&'*+.^_`|~-]+$" },
|
|
31711
|
+
additionalProperties: { type: "string" }
|
|
31712
|
+
},
|
|
31707
31713
|
idempotency_key_header: {
|
|
31708
31714
|
type: "string",
|
|
31709
31715
|
minLength: 1,
|
|
@@ -35788,6 +35794,22 @@ var FLAG_REGISTRY = [
|
|
|
35788
35794
|
// registry-only (ADR-0022). NOT `public`: it is resolved server-side only, so it
|
|
35789
35795
|
// must never be serialized into the browser map.
|
|
35790
35796
|
defaultValue: false
|
|
35797
|
+
},
|
|
35798
|
+
{
|
|
35799
|
+
key: "ninjafy-brand",
|
|
35800
|
+
description: 'Present the product under the Ninjafy brand instead of Augmented Team (ENG-8250). This is the UMBRELLA brand gate, not a one-off nav toggle: every subsequent rebrand surface (page titles, email templates, marketing-facing copy) reads THIS key rather than adding its own flag, so the whole rebrand keeps a single kill switch. First surface is the left-hand nav wordmark \u2014 ON replaces the human+robot mark and the "augmented.team" text with italic lowercase "ninjafy"; OFF renders exactly what shipped before. Scope is USER-FACING BRAND TEXT ONLY: it must never gate a code identifier, package name, env var or CLI name, which stay `Augmented`/`agt` per the CLAUDE.md naming contract (the deep code rename is workstream C of docs/runbooks/rebrand-ninjafy-migration.md and is out of scope here). Set the stage-wide default to flip a whole environment, or add a feature_flag_overrides row to pilot one organization while every other org still sees Augmented. Ships dark.',
|
|
35801
|
+
flagType: "boolean",
|
|
35802
|
+
// Declared safe value is `false`: the pre-rebrand brand. `false` is also the
|
|
35803
|
+
// fail-closed direction — if the flag DB is unreachable we must show the brand
|
|
35804
|
+
// that is currently live and contractually correct, never leak an unannounced
|
|
35805
|
+
// rebrand to every customer at once.
|
|
35806
|
+
defaultValue: false,
|
|
35807
|
+
// Read CLIENT-SIDE: sidebar.tsx is a "use client" component and resolves this
|
|
35808
|
+
// via usePublicBooleanFlag, so the key must be in the browser-exposed public
|
|
35809
|
+
// map. Unlike onboarding-msteams-channel above there is no wrong-org hazard —
|
|
35810
|
+
// the sidebar renders inside the active-org cookie's scope, which is exactly
|
|
35811
|
+
// the org whose brand should be shown.
|
|
35812
|
+
public: true
|
|
35791
35813
|
}
|
|
35792
35814
|
];
|
|
35793
35815
|
var REGISTRY_BY_KEY = new Map(FLAG_REGISTRY.map((definition) => [definition.key, definition]));
|
package/dist/mcp/origami.js
CHANGED
|
@@ -37203,6 +37203,12 @@ var integration_metadata_v1_default = {
|
|
|
37203
37203
|
description: "Optional query-string shape with `{arg}` placeholders.",
|
|
37204
37204
|
additionalProperties: { type: "string" }
|
|
37205
37205
|
},
|
|
37206
|
+
headers_template: {
|
|
37207
|
+
type: "object",
|
|
37208
|
+
description: 'Optional request-header shape with `{arg}` placeholders (e.g. `{ "x-origami-project": "{project_id}" }`). A header whose template resolves to empty is dropped rather than sent blank, and args consumed only by a header template are excluded from a `{$body}` expansion.',
|
|
37209
|
+
propertyNames: { pattern: "^[A-Za-z0-9!#$%&'*+.^_`|~-]+$" },
|
|
37210
|
+
additionalProperties: { type: "string" }
|
|
37211
|
+
},
|
|
37206
37212
|
idempotency_key_header: {
|
|
37207
37213
|
type: "string",
|
|
37208
37214
|
minLength: 1,
|
|
@@ -37249,7 +37255,7 @@ var FIXED_SECONDS = {
|
|
|
37249
37255
|
var PLACEHOLDER_RE = /\{([a-zA-Z_][a-zA-Z0-9_]*)\}/g;
|
|
37250
37256
|
function buildHttpRequest(input) {
|
|
37251
37257
|
const { tool, args, baseUrl, bearerToken, requestId, extraHeaders } = input;
|
|
37252
|
-
const { method, path_template, query_template, body_template, idempotency_key_header } = tool.http;
|
|
37258
|
+
const { method, path_template, query_template, headers_template, body_template, idempotency_key_header } = tool.http;
|
|
37253
37259
|
const path = templatePath(path_template, args);
|
|
37254
37260
|
const query = query_template ? buildQueryString(query_template, args) : "";
|
|
37255
37261
|
const url2 = joinUrl(baseUrl, path) + query;
|
|
@@ -37263,9 +37269,17 @@ function buildHttpRequest(input) {
|
|
|
37263
37269
|
const headerName = idempotency_key_header ?? "Idempotency-Key";
|
|
37264
37270
|
headers[headerName] = requestId;
|
|
37265
37271
|
}
|
|
37272
|
+
if (headers_template) {
|
|
37273
|
+
const reserved = /* @__PURE__ */ new Set([
|
|
37274
|
+
...RESERVED_HEADER_NAMES,
|
|
37275
|
+
(idempotency_key_header ?? "Idempotency-Key").toLowerCase()
|
|
37276
|
+
]);
|
|
37277
|
+
Object.assign(headers, buildTemplatedHeaders(headers_template, args, reserved));
|
|
37278
|
+
}
|
|
37266
37279
|
let body;
|
|
37267
37280
|
if (method !== "GET" && body_template !== void 0) {
|
|
37268
|
-
const
|
|
37281
|
+
const bodyArgs = body_template === "{$body}" && headers_template ? omitKeys(args, headerOnlyPlaceholders(headers_template, tool.http)) : args;
|
|
37282
|
+
const expanded = expandBodyTemplate(body_template, bodyArgs);
|
|
37269
37283
|
body = JSON.stringify(expanded);
|
|
37270
37284
|
headers["Content-Type"] = "application/json";
|
|
37271
37285
|
}
|
|
@@ -37274,6 +37288,65 @@ function buildHttpRequest(input) {
|
|
|
37274
37288
|
}
|
|
37275
37289
|
return { url: url2, method, headers, body };
|
|
37276
37290
|
}
|
|
37291
|
+
var RESERVED_HEADER_NAMES = /* @__PURE__ */ new Set(["authorization", "accept", "content-type"]);
|
|
37292
|
+
function buildTemplatedHeaders(template, args, reservedNames) {
|
|
37293
|
+
const out = {};
|
|
37294
|
+
for (const [headerName, valueTemplate] of Object.entries(template)) {
|
|
37295
|
+
if (!isValidHeaderName(headerName)) {
|
|
37296
|
+
throw new TemplateError(`invalid header name in headers_template: ${headerName}`);
|
|
37297
|
+
}
|
|
37298
|
+
if (reservedNames.has(headerName.toLowerCase())) {
|
|
37299
|
+
throw new TemplateError(`headers_template cannot target reserved header: ${headerName}`);
|
|
37300
|
+
}
|
|
37301
|
+
const expanded = valueTemplate.replace(PLACEHOLDER_RE, (_full, key) => {
|
|
37302
|
+
const v = args[key];
|
|
37303
|
+
if (v === void 0 || v === null)
|
|
37304
|
+
return "";
|
|
37305
|
+
if (!isScalar(v)) {
|
|
37306
|
+
throw new TemplateError(`header placeholder {${key}} cannot be substituted with non-scalar value`);
|
|
37307
|
+
}
|
|
37308
|
+
return String(v);
|
|
37309
|
+
});
|
|
37310
|
+
if (expanded === "")
|
|
37311
|
+
continue;
|
|
37312
|
+
if (!isValidHeaderValue(expanded)) {
|
|
37313
|
+
throw new TemplateError(`header ${headerName} resolved to an invalid value`);
|
|
37314
|
+
}
|
|
37315
|
+
out[headerName] = expanded;
|
|
37316
|
+
}
|
|
37317
|
+
return out;
|
|
37318
|
+
}
|
|
37319
|
+
function headerOnlyPlaceholders(headersTemplate, http) {
|
|
37320
|
+
const elsewhere = /* @__PURE__ */ new Set([
|
|
37321
|
+
...placeholderKeys(http.path_template),
|
|
37322
|
+
...Object.values(http.query_template ?? {}).flatMap(placeholderKeys)
|
|
37323
|
+
]);
|
|
37324
|
+
const out = /* @__PURE__ */ new Set();
|
|
37325
|
+
for (const key of Object.values(headersTemplate).flatMap(placeholderKeys)) {
|
|
37326
|
+
if (!elsewhere.has(key))
|
|
37327
|
+
out.add(key);
|
|
37328
|
+
}
|
|
37329
|
+
return out;
|
|
37330
|
+
}
|
|
37331
|
+
function placeholderKeys(template) {
|
|
37332
|
+
return [...template.matchAll(PLACEHOLDER_RE)].map((m) => m[1]);
|
|
37333
|
+
}
|
|
37334
|
+
function omitKeys(args, keys) {
|
|
37335
|
+
if (keys.size === 0)
|
|
37336
|
+
return args;
|
|
37337
|
+
const out = {};
|
|
37338
|
+
for (const [k, v] of Object.entries(args)) {
|
|
37339
|
+
if (!keys.has(k))
|
|
37340
|
+
out[k] = v;
|
|
37341
|
+
}
|
|
37342
|
+
return out;
|
|
37343
|
+
}
|
|
37344
|
+
function isValidHeaderName(name) {
|
|
37345
|
+
return /^[A-Za-z0-9!#$%&'*+.^_`|~-]+$/.test(name);
|
|
37346
|
+
}
|
|
37347
|
+
function isValidHeaderValue(value) {
|
|
37348
|
+
return !/[\x00-\x1f\x7f]/.test(value);
|
|
37349
|
+
}
|
|
37277
37350
|
function templatePath(template, args) {
|
|
37278
37351
|
return template.replace(PLACEHOLDER_RE, (_full, key) => {
|
|
37279
37352
|
const value = args[key];
|
|
@@ -41133,6 +41206,22 @@ var FLAG_REGISTRY = [
|
|
|
41133
41206
|
// registry-only (ADR-0022). NOT `public`: it is resolved server-side only, so it
|
|
41134
41207
|
// must never be serialized into the browser map.
|
|
41135
41208
|
defaultValue: false
|
|
41209
|
+
},
|
|
41210
|
+
{
|
|
41211
|
+
key: "ninjafy-brand",
|
|
41212
|
+
description: 'Present the product under the Ninjafy brand instead of Augmented Team (ENG-8250). This is the UMBRELLA brand gate, not a one-off nav toggle: every subsequent rebrand surface (page titles, email templates, marketing-facing copy) reads THIS key rather than adding its own flag, so the whole rebrand keeps a single kill switch. First surface is the left-hand nav wordmark \u2014 ON replaces the human+robot mark and the "augmented.team" text with italic lowercase "ninjafy"; OFF renders exactly what shipped before. Scope is USER-FACING BRAND TEXT ONLY: it must never gate a code identifier, package name, env var or CLI name, which stay `Augmented`/`agt` per the CLAUDE.md naming contract (the deep code rename is workstream C of docs/runbooks/rebrand-ninjafy-migration.md and is out of scope here). Set the stage-wide default to flip a whole environment, or add a feature_flag_overrides row to pilot one organization while every other org still sees Augmented. Ships dark.',
|
|
41213
|
+
flagType: "boolean",
|
|
41214
|
+
// Declared safe value is `false`: the pre-rebrand brand. `false` is also the
|
|
41215
|
+
// fail-closed direction — if the flag DB is unreachable we must show the brand
|
|
41216
|
+
// that is currently live and contractually correct, never leak an unannounced
|
|
41217
|
+
// rebrand to every customer at once.
|
|
41218
|
+
defaultValue: false,
|
|
41219
|
+
// Read CLIENT-SIDE: sidebar.tsx is a "use client" component and resolves this
|
|
41220
|
+
// via usePublicBooleanFlag, so the key must be in the browser-exposed public
|
|
41221
|
+
// map. Unlike onboarding-msteams-channel above there is no wrong-org hazard —
|
|
41222
|
+
// the sidebar renders inside the active-org cookie's scope, which is exactly
|
|
41223
|
+
// the org whose brand should be shown.
|
|
41224
|
+
public: true
|
|
41136
41225
|
}
|
|
41137
41226
|
];
|
|
41138
41227
|
var REGISTRY_BY_KEY = new Map(FLAG_REGISTRY.map((definition) => [definition.key, definition]));
|
|
@@ -41182,6 +41271,10 @@ var IdentityError = class extends Error {
|
|
|
41182
41271
|
this.status = status;
|
|
41183
41272
|
}
|
|
41184
41273
|
};
|
|
41274
|
+
function nonEmpty(value) {
|
|
41275
|
+
const trimmed = typeof value === "string" ? value.trim() : "";
|
|
41276
|
+
return trimmed === "" ? null : trimmed;
|
|
41277
|
+
}
|
|
41185
41278
|
var IdentityResolver = class {
|
|
41186
41279
|
env;
|
|
41187
41280
|
fetchImpl;
|
|
@@ -41209,7 +41302,10 @@ var IdentityResolver = class {
|
|
|
41209
41302
|
return {
|
|
41210
41303
|
apiKey,
|
|
41211
41304
|
organizationId: this.env.ORIGAMI_ORG_ID ?? null,
|
|
41212
|
-
teamSlug: this.env.ORIGAMI_TEAM_SLUG ?? null
|
|
41305
|
+
teamSlug: this.env.ORIGAMI_TEAM_SLUG ?? null,
|
|
41306
|
+
// Blank is absent: an empty ORIGAMI_PROJECT_ID must mean "parent org",
|
|
41307
|
+
// not "scope to the empty string" (which the vendor 400s on).
|
|
41308
|
+
projectId: nonEmpty(this.env.ORIGAMI_PROJECT_ID)
|
|
41213
41309
|
};
|
|
41214
41310
|
}
|
|
41215
41311
|
async resolveViaBroker() {
|
|
@@ -41255,7 +41351,8 @@ var IdentityResolver = class {
|
|
|
41255
41351
|
return {
|
|
41256
41352
|
apiKey: data.access_token,
|
|
41257
41353
|
organizationId: data.organization_id ?? null,
|
|
41258
|
-
teamSlug: data.team_slug ?? null
|
|
41354
|
+
teamSlug: data.team_slug ?? null,
|
|
41355
|
+
projectId: nonEmpty(data.project_id)
|
|
41259
41356
|
};
|
|
41260
41357
|
}
|
|
41261
41358
|
throw new IdentityError(401, "Credential fetch failed after JWT re-exchange retry");
|
|
@@ -41297,80 +41394,36 @@ var IdentityResolver = class {
|
|
|
41297
41394
|
}
|
|
41298
41395
|
};
|
|
41299
41396
|
|
|
41300
|
-
// src/
|
|
41301
|
-
var
|
|
41302
|
-
var
|
|
41303
|
-
|
|
41304
|
-
|
|
41305
|
-
|
|
41306
|
-
|
|
41307
|
-
|
|
41308
|
-
|
|
41309
|
-
|
|
41310
|
-
|
|
41311
|
-
|
|
41312
|
-
|
|
41313
|
-
|
|
41314
|
-
|
|
41315
|
-
|
|
41316
|
-
|
|
41317
|
-
|
|
41318
|
-
|
|
41319
|
-
|
|
41320
|
-
|
|
41321
|
-
|
|
41322
|
-
|
|
41323
|
-
const descriptor = byName.get(req.params.name);
|
|
41324
|
-
if (!descriptor) {
|
|
41325
|
-
return errorResult(`unknown tool ${req.params.name}`);
|
|
41326
|
-
}
|
|
41327
|
-
const args = req.params.arguments ?? {};
|
|
41328
|
-
let identity;
|
|
41329
|
-
try {
|
|
41330
|
-
identity = await opts.resolveIdentity();
|
|
41331
|
-
} catch (err) {
|
|
41332
|
-
const msg = err instanceof IdentityError ? err.message : err.message;
|
|
41333
|
-
return errorResult(`credential resolution failed: ${msg}`);
|
|
41334
|
-
}
|
|
41335
|
-
const extraHeaders = {};
|
|
41336
|
-
if (identity.organizationId) extraHeaders["X-Organization-Id"] = identity.organizationId;
|
|
41337
|
-
if (identity.teamSlug) extraHeaders["X-Team-Slug"] = identity.teamSlug;
|
|
41338
|
-
let prepared;
|
|
41339
|
-
try {
|
|
41340
|
-
prepared = buildHttpRequest({
|
|
41341
|
-
tool: descriptor,
|
|
41342
|
-
args,
|
|
41343
|
-
baseUrl,
|
|
41344
|
-
bearerToken: identity.apiKey,
|
|
41345
|
-
requestId: newRequestId(),
|
|
41346
|
-
extraHeaders
|
|
41347
|
-
});
|
|
41348
|
-
} catch (err) {
|
|
41349
|
-
const msg = err instanceof TemplateError ? err.message : err.message;
|
|
41350
|
-
return errorResult(msg);
|
|
41351
|
-
}
|
|
41352
|
-
let resp;
|
|
41353
|
-
try {
|
|
41354
|
-
resp = await fetchImpl(prepared.url, {
|
|
41355
|
-
method: prepared.method,
|
|
41356
|
-
headers: prepared.headers,
|
|
41357
|
-
body: prepared.body,
|
|
41358
|
-
signal: AbortSignal.timeout(VENDOR_TIMEOUT_MS)
|
|
41359
|
-
});
|
|
41360
|
-
} catch (err) {
|
|
41361
|
-
return errorResult(`origami.chat fetch failed: ${err.message}`);
|
|
41362
|
-
}
|
|
41363
|
-
const text = await resp.text();
|
|
41364
|
-
if (!resp.ok) {
|
|
41365
|
-
return errorResult(`origami.chat ${resp.status}: ${text.slice(0, 400)}`);
|
|
41397
|
+
// src/descriptors.ts
|
|
41398
|
+
var PROJECT_SCOPE_HEADER = "x-origami-project";
|
|
41399
|
+
var PROJECT_ID_ARG = "project_id";
|
|
41400
|
+
var PROJECT_ID_PROPERTY = {
|
|
41401
|
+
type: ["string", "null"],
|
|
41402
|
+
description: "Optional origami project (child org) id to scope this call to - discover ids with list_projects. Omit to act on the parent org that owns the API key. If the integration has a default project configured it is applied automatically when this is omitted; pass null to override that default and act on the parent org."
|
|
41403
|
+
};
|
|
41404
|
+
function withProjectScoping(tool) {
|
|
41405
|
+
return {
|
|
41406
|
+
...tool,
|
|
41407
|
+
input_schema: {
|
|
41408
|
+
...tool.input_schema,
|
|
41409
|
+
properties: {
|
|
41410
|
+
...tool.input_schema.properties,
|
|
41411
|
+
[PROJECT_ID_ARG]: PROJECT_ID_PROPERTY
|
|
41412
|
+
}
|
|
41413
|
+
},
|
|
41414
|
+
http: {
|
|
41415
|
+
...tool.http,
|
|
41416
|
+
headers_template: {
|
|
41417
|
+
...tool.http.headers_template ?? {},
|
|
41418
|
+
[PROJECT_SCOPE_HEADER]: `{${PROJECT_ID_ARG}}`
|
|
41419
|
+
}
|
|
41366
41420
|
}
|
|
41367
|
-
|
|
41368
|
-
});
|
|
41369
|
-
return server;
|
|
41421
|
+
};
|
|
41370
41422
|
}
|
|
41371
|
-
|
|
41372
|
-
|
|
41373
|
-
|
|
41423
|
+
function supportsProjectScoping(tool) {
|
|
41424
|
+
return tool.http.headers_template?.[PROJECT_SCOPE_HEADER] === `{${PROJECT_ID_ARG}}`;
|
|
41425
|
+
}
|
|
41426
|
+
var ORG_SCOPED_TOOLS = [
|
|
41374
41427
|
// ==========================================================================
|
|
41375
41428
|
// v1 DATA PLANE
|
|
41376
41429
|
// ==========================================================================
|
|
@@ -41650,6 +41703,122 @@ var ORIGAMI_TOOLS = [
|
|
|
41650
41703
|
}
|
|
41651
41704
|
}
|
|
41652
41705
|
];
|
|
41706
|
+
var PROJECT_TOOLS = [
|
|
41707
|
+
{
|
|
41708
|
+
name: "list_projects",
|
|
41709
|
+
description: "List the projects (child orgs) under the API key's parent org, newest first. Use this to discover the project id to pass as `project_id` on any other tool - without it every call resolves against the parent org, so a project's agents and tables are invisible. Cursor-paginated: pass the previous response's `nextCursor` as `cursor`; `nextCursor: null` means the last page. Optional `search` is a case-insensitive substring match on project name. Returns { object, items[{ id, name, monthlyCredits, usage{spent,reserved}, createdAt }], nextCursor }. Always acts on the parent org - `project_id` is not accepted here.",
|
|
41710
|
+
risk_tier: "Low",
|
|
41711
|
+
input_schema: {
|
|
41712
|
+
type: "object",
|
|
41713
|
+
properties: {
|
|
41714
|
+
cursor: { type: "string", description: "Opaque pagination cursor - the `nextCursor` from a previous page. Omit for the first page." },
|
|
41715
|
+
limit: { type: "integer", minimum: 1, maximum: 100, description: "Projects per page. Default 50, max 100." },
|
|
41716
|
+
search: { type: "string", description: "Optional case-insensitive substring match on project name." }
|
|
41717
|
+
}
|
|
41718
|
+
},
|
|
41719
|
+
http: {
|
|
41720
|
+
method: "GET",
|
|
41721
|
+
path_template: "/api/v2/projects",
|
|
41722
|
+
query_template: { cursor: "{cursor}", limit: "{limit}", search: "{search}" }
|
|
41723
|
+
}
|
|
41724
|
+
},
|
|
41725
|
+
{
|
|
41726
|
+
name: "get_project",
|
|
41727
|
+
description: "Fetch a single project (child org) by id: name, optional monthlyCredits budget cap, current-period usage { spent, reserved } and createdAt. Use it to confirm a project id before scoping calls to it, or to check its remaining budget. Always acts on the parent org - `project_id` is not accepted here.",
|
|
41728
|
+
risk_tier: "Low",
|
|
41729
|
+
input_schema: {
|
|
41730
|
+
type: "object",
|
|
41731
|
+
properties: {
|
|
41732
|
+
projectId: { type: "string", minLength: 1, description: "The project (child org) id (uuid), from list_projects." }
|
|
41733
|
+
},
|
|
41734
|
+
required: ["projectId"]
|
|
41735
|
+
},
|
|
41736
|
+
http: { method: "GET", path_template: "/api/v2/projects/{projectId}" }
|
|
41737
|
+
}
|
|
41738
|
+
];
|
|
41739
|
+
var ORIGAMI_TOOLS = [
|
|
41740
|
+
...ORG_SCOPED_TOOLS.map(withProjectScoping),
|
|
41741
|
+
...PROJECT_TOOLS
|
|
41742
|
+
];
|
|
41743
|
+
|
|
41744
|
+
// src/server.ts
|
|
41745
|
+
var DEFAULT_BASE_URL = "https://origami.chat";
|
|
41746
|
+
var VENDOR_TIMEOUT_MS = 3e4;
|
|
41747
|
+
function errorResult(text) {
|
|
41748
|
+
return { isError: true, content: [{ type: "text", text: `Error: ${text}` }] };
|
|
41749
|
+
}
|
|
41750
|
+
function resolveProjectScope(descriptor, args, defaultProjectId) {
|
|
41751
|
+
if (!defaultProjectId) return args;
|
|
41752
|
+
if (!supportsProjectScoping(descriptor)) return args;
|
|
41753
|
+
if (PROJECT_ID_ARG in args) return args;
|
|
41754
|
+
return { ...args, [PROJECT_ID_ARG]: defaultProjectId };
|
|
41755
|
+
}
|
|
41756
|
+
function buildOrigamiMcpServer(opts) {
|
|
41757
|
+
const baseUrl = opts.baseUrl ?? DEFAULT_BASE_URL;
|
|
41758
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
41759
|
+
const newRequestId = opts.newRequestId ?? (() => crypto.randomUUID());
|
|
41760
|
+
const byName = new Map(opts.descriptors.map((d) => [d.name, d]));
|
|
41761
|
+
const server = new Server(
|
|
41762
|
+
{ name: "origami", version: "0.1.0" },
|
|
41763
|
+
{ capabilities: { tools: {} } }
|
|
41764
|
+
);
|
|
41765
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
41766
|
+
tools: opts.descriptors.map((d) => ({
|
|
41767
|
+
name: d.name,
|
|
41768
|
+
description: d.description,
|
|
41769
|
+
inputSchema: d.input_schema
|
|
41770
|
+
}))
|
|
41771
|
+
}));
|
|
41772
|
+
server.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
41773
|
+
const descriptor = byName.get(req.params.name);
|
|
41774
|
+
if (!descriptor) {
|
|
41775
|
+
return errorResult(`unknown tool ${req.params.name}`);
|
|
41776
|
+
}
|
|
41777
|
+
const args = req.params.arguments ?? {};
|
|
41778
|
+
let identity;
|
|
41779
|
+
try {
|
|
41780
|
+
identity = await opts.resolveIdentity();
|
|
41781
|
+
} catch (err) {
|
|
41782
|
+
const msg = err instanceof IdentityError ? err.message : err.message;
|
|
41783
|
+
return errorResult(`credential resolution failed: ${msg}`);
|
|
41784
|
+
}
|
|
41785
|
+
const extraHeaders = {};
|
|
41786
|
+
if (identity.organizationId) extraHeaders["X-Organization-Id"] = identity.organizationId;
|
|
41787
|
+
if (identity.teamSlug) extraHeaders["X-Team-Slug"] = identity.teamSlug;
|
|
41788
|
+
const scopedArgs = resolveProjectScope(descriptor, args, identity.projectId);
|
|
41789
|
+
let prepared;
|
|
41790
|
+
try {
|
|
41791
|
+
prepared = buildHttpRequest({
|
|
41792
|
+
tool: descriptor,
|
|
41793
|
+
args: scopedArgs,
|
|
41794
|
+
baseUrl,
|
|
41795
|
+
bearerToken: identity.apiKey,
|
|
41796
|
+
requestId: newRequestId(),
|
|
41797
|
+
extraHeaders
|
|
41798
|
+
});
|
|
41799
|
+
} catch (err) {
|
|
41800
|
+
const msg = err instanceof TemplateError ? err.message : err.message;
|
|
41801
|
+
return errorResult(msg);
|
|
41802
|
+
}
|
|
41803
|
+
let resp;
|
|
41804
|
+
try {
|
|
41805
|
+
resp = await fetchImpl(prepared.url, {
|
|
41806
|
+
method: prepared.method,
|
|
41807
|
+
headers: prepared.headers,
|
|
41808
|
+
body: prepared.body,
|
|
41809
|
+
signal: AbortSignal.timeout(VENDOR_TIMEOUT_MS)
|
|
41810
|
+
});
|
|
41811
|
+
} catch (err) {
|
|
41812
|
+
return errorResult(`origami.chat fetch failed: ${err.message}`);
|
|
41813
|
+
}
|
|
41814
|
+
const text = await resp.text();
|
|
41815
|
+
if (!resp.ok) {
|
|
41816
|
+
return errorResult(`origami.chat ${resp.status}: ${text.slice(0, 400)}`);
|
|
41817
|
+
}
|
|
41818
|
+
return { content: [{ type: "text", text: text || "{}" }] };
|
|
41819
|
+
});
|
|
41820
|
+
return server;
|
|
41821
|
+
}
|
|
41653
41822
|
|
|
41654
41823
|
// src/index.ts
|
|
41655
41824
|
async function main() {
|
|
@@ -31312,6 +31312,12 @@ var integration_metadata_v1_default = {
|
|
|
31312
31312
|
description: "Optional query-string shape with `{arg}` placeholders.",
|
|
31313
31313
|
additionalProperties: { type: "string" }
|
|
31314
31314
|
},
|
|
31315
|
+
headers_template: {
|
|
31316
|
+
type: "object",
|
|
31317
|
+
description: 'Optional request-header shape with `{arg}` placeholders (e.g. `{ "x-origami-project": "{project_id}" }`). A header whose template resolves to empty is dropped rather than sent blank, and args consumed only by a header template are excluded from a `{$body}` expansion.',
|
|
31318
|
+
propertyNames: { pattern: "^[A-Za-z0-9!#$%&'*+.^_`|~-]+$" },
|
|
31319
|
+
additionalProperties: { type: "string" }
|
|
31320
|
+
},
|
|
31315
31321
|
idempotency_key_header: {
|
|
31316
31322
|
type: "string",
|
|
31317
31323
|
minLength: 1,
|
|
@@ -35396,6 +35402,22 @@ var FLAG_REGISTRY = [
|
|
|
35396
35402
|
// registry-only (ADR-0022). NOT `public`: it is resolved server-side only, so it
|
|
35397
35403
|
// must never be serialized into the browser map.
|
|
35398
35404
|
defaultValue: false
|
|
35405
|
+
},
|
|
35406
|
+
{
|
|
35407
|
+
key: "ninjafy-brand",
|
|
35408
|
+
description: 'Present the product under the Ninjafy brand instead of Augmented Team (ENG-8250). This is the UMBRELLA brand gate, not a one-off nav toggle: every subsequent rebrand surface (page titles, email templates, marketing-facing copy) reads THIS key rather than adding its own flag, so the whole rebrand keeps a single kill switch. First surface is the left-hand nav wordmark \u2014 ON replaces the human+robot mark and the "augmented.team" text with italic lowercase "ninjafy"; OFF renders exactly what shipped before. Scope is USER-FACING BRAND TEXT ONLY: it must never gate a code identifier, package name, env var or CLI name, which stay `Augmented`/`agt` per the CLAUDE.md naming contract (the deep code rename is workstream C of docs/runbooks/rebrand-ninjafy-migration.md and is out of scope here). Set the stage-wide default to flip a whole environment, or add a feature_flag_overrides row to pilot one organization while every other org still sees Augmented. Ships dark.',
|
|
35409
|
+
flagType: "boolean",
|
|
35410
|
+
// Declared safe value is `false`: the pre-rebrand brand. `false` is also the
|
|
35411
|
+
// fail-closed direction — if the flag DB is unreachable we must show the brand
|
|
35412
|
+
// that is currently live and contractually correct, never leak an unannounced
|
|
35413
|
+
// rebrand to every customer at once.
|
|
35414
|
+
defaultValue: false,
|
|
35415
|
+
// Read CLIENT-SIDE: sidebar.tsx is a "use client" component and resolves this
|
|
35416
|
+
// via usePublicBooleanFlag, so the key must be in the browser-exposed public
|
|
35417
|
+
// map. Unlike onboarding-msteams-channel above there is no wrong-org hazard —
|
|
35418
|
+
// the sidebar renders inside the active-org cookie's scope, which is exactly
|
|
35419
|
+
// the org whose brand should be shown.
|
|
35420
|
+
public: true
|
|
35399
35421
|
}
|
|
35400
35422
|
];
|
|
35401
35423
|
var REGISTRY_BY_KEY = new Map(FLAG_REGISTRY.map((definition) => [definition.key, definition]));
|
|
@@ -31614,6 +31614,12 @@ var integration_metadata_v1_default = {
|
|
|
31614
31614
|
description: "Optional query-string shape with `{arg}` placeholders.",
|
|
31615
31615
|
additionalProperties: { type: "string" }
|
|
31616
31616
|
},
|
|
31617
|
+
headers_template: {
|
|
31618
|
+
type: "object",
|
|
31619
|
+
description: 'Optional request-header shape with `{arg}` placeholders (e.g. `{ "x-origami-project": "{project_id}" }`). A header whose template resolves to empty is dropped rather than sent blank, and args consumed only by a header template are excluded from a `{$body}` expansion.',
|
|
31620
|
+
propertyNames: { pattern: "^[A-Za-z0-9!#$%&'*+.^_`|~-]+$" },
|
|
31621
|
+
additionalProperties: { type: "string" }
|
|
31622
|
+
},
|
|
31617
31623
|
idempotency_key_header: {
|
|
31618
31624
|
type: "string",
|
|
31619
31625
|
minLength: 1,
|
|
@@ -35698,6 +35704,22 @@ var FLAG_REGISTRY = [
|
|
|
35698
35704
|
// registry-only (ADR-0022). NOT `public`: it is resolved server-side only, so it
|
|
35699
35705
|
// must never be serialized into the browser map.
|
|
35700
35706
|
defaultValue: false
|
|
35707
|
+
},
|
|
35708
|
+
{
|
|
35709
|
+
key: "ninjafy-brand",
|
|
35710
|
+
description: 'Present the product under the Ninjafy brand instead of Augmented Team (ENG-8250). This is the UMBRELLA brand gate, not a one-off nav toggle: every subsequent rebrand surface (page titles, email templates, marketing-facing copy) reads THIS key rather than adding its own flag, so the whole rebrand keeps a single kill switch. First surface is the left-hand nav wordmark \u2014 ON replaces the human+robot mark and the "augmented.team" text with italic lowercase "ninjafy"; OFF renders exactly what shipped before. Scope is USER-FACING BRAND TEXT ONLY: it must never gate a code identifier, package name, env var or CLI name, which stay `Augmented`/`agt` per the CLAUDE.md naming contract (the deep code rename is workstream C of docs/runbooks/rebrand-ninjafy-migration.md and is out of scope here). Set the stage-wide default to flip a whole environment, or add a feature_flag_overrides row to pilot one organization while every other org still sees Augmented. Ships dark.',
|
|
35711
|
+
flagType: "boolean",
|
|
35712
|
+
// Declared safe value is `false`: the pre-rebrand brand. `false` is also the
|
|
35713
|
+
// fail-closed direction — if the flag DB is unreachable we must show the brand
|
|
35714
|
+
// that is currently live and contractually correct, never leak an unannounced
|
|
35715
|
+
// rebrand to every customer at once.
|
|
35716
|
+
defaultValue: false,
|
|
35717
|
+
// Read CLIENT-SIDE: sidebar.tsx is a "use client" component and resolves this
|
|
35718
|
+
// via usePublicBooleanFlag, so the key must be in the browser-exposed public
|
|
35719
|
+
// map. Unlike onboarding-msteams-channel above there is no wrong-org hazard —
|
|
35720
|
+
// the sidebar renders inside the active-org cookie's scope, which is exactly
|
|
35721
|
+
// the org whose brand should be shown.
|
|
35722
|
+
public: true
|
|
35701
35723
|
}
|
|
35702
35724
|
];
|
|
35703
35725
|
var REGISTRY_BY_KEY = new Map(FLAG_REGISTRY.map((definition) => [definition.key, definition]));
|
|
@@ -36,7 +36,7 @@ import {
|
|
|
36
36
|
writeDirectChatSessionState,
|
|
37
37
|
writeEgressAllowlist,
|
|
38
38
|
writePersistentClaudeWrapper
|
|
39
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-KAIH24HZ.js";
|
|
40
40
|
import "./chunk-XWVM4KPK.js";
|
|
41
41
|
export {
|
|
42
42
|
EGRESS_BASELINE_DOMAINS,
|
|
@@ -77,4 +77,4 @@ export {
|
|
|
77
77
|
writeEgressAllowlist,
|
|
78
78
|
writePersistentClaudeWrapper
|
|
79
79
|
};
|
|
80
|
-
//# sourceMappingURL=persistent-session-
|
|
80
|
+
//# sourceMappingURL=persistent-session-EVLWDI3I.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
paneLogPath
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-KAIH24HZ.js";
|
|
4
4
|
import "./chunk-XWVM4KPK.js";
|
|
5
5
|
|
|
6
6
|
// src/lib/responsiveness-probe.ts
|
|
@@ -528,4 +528,4 @@ export {
|
|
|
528
528
|
readAndResetSlackReplyBindingClassifications,
|
|
529
529
|
readAndResetSlackReplyTargetClassifications
|
|
530
530
|
};
|
|
531
|
-
//# sourceMappingURL=responsiveness-probe-
|
|
531
|
+
//# sourceMappingURL=responsiveness-probe-EGP2F3WD.js.map
|