@dudousxd/nestjs-agent-core 0.36.0 → 0.37.0
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/index.cjs +338 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +254 -1
- package/dist/index.d.ts +254 -1
- package/dist/index.js +324 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -27,6 +27,7 @@ var AGENT_APPROVAL_PORT = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:app
|
|
|
27
27
|
var AGENT_SKILLS = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:skills");
|
|
28
28
|
var AGENT_MEMORY = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:memory");
|
|
29
29
|
var AGENT_SKILL_SOURCES = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:skill-sources");
|
|
30
|
+
var AGENT_CONFIRM_TOKEN_STORE = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:confirm-token-store");
|
|
30
31
|
|
|
31
32
|
// src/spi/model-catalog.ts
|
|
32
33
|
function staticModelCatalog(view) {
|
|
@@ -5787,11 +5788,321 @@ var InMemoryAgentStore = class {
|
|
|
5787
5788
|
};
|
|
5788
5789
|
}
|
|
5789
5790
|
};
|
|
5791
|
+
|
|
5792
|
+
// src/confirm-token.ts
|
|
5793
|
+
import { createHash as createHash2, createHmac, timingSafeEqual } from "crypto";
|
|
5794
|
+
var DEFAULT_CONFIRM_TTL_MS = 15 * 60 * 1e3;
|
|
5795
|
+
function canonicalJson(value) {
|
|
5796
|
+
if (value === void 0) return "null";
|
|
5797
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "null";
|
|
5798
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
5799
|
+
if (typeof value.toJSON === "function") {
|
|
5800
|
+
return canonicalJson(value.toJSON());
|
|
5801
|
+
}
|
|
5802
|
+
const entries = Object.entries(value).filter(([, entry]) => entry !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0);
|
|
5803
|
+
return `{${entries.map(([key, entry]) => `${JSON.stringify(key)}:${canonicalJson(entry)}`).join(",")}}`;
|
|
5804
|
+
}
|
|
5805
|
+
__name(canonicalJson, "canonicalJson");
|
|
5806
|
+
function signature(subject, expiresAt, secret) {
|
|
5807
|
+
if (secret === "") {
|
|
5808
|
+
throw new Error("confirm token: the secret is empty");
|
|
5809
|
+
}
|
|
5810
|
+
return createHmac("sha256", secret).update(canonicalJson([
|
|
5811
|
+
"agent-confirm",
|
|
5812
|
+
subject.tool,
|
|
5813
|
+
subject.actorId,
|
|
5814
|
+
subject.tenantRef ?? "",
|
|
5815
|
+
expiresAt,
|
|
5816
|
+
subject.args
|
|
5817
|
+
])).digest("base64url");
|
|
5818
|
+
}
|
|
5819
|
+
__name(signature, "signature");
|
|
5820
|
+
function signConfirmToken(subject, options) {
|
|
5821
|
+
return `${options.expiresAt}.${signature(subject, options.expiresAt, options.secret)}`;
|
|
5822
|
+
}
|
|
5823
|
+
__name(signConfirmToken, "signConfirmToken");
|
|
5824
|
+
function confirmTokenExpiry(token) {
|
|
5825
|
+
const separator = token.indexOf(".");
|
|
5826
|
+
if (separator <= 0) return void 0;
|
|
5827
|
+
const expiresAt = Number(token.slice(0, separator));
|
|
5828
|
+
return Number.isSafeInteger(expiresAt) && expiresAt > 0 ? expiresAt : void 0;
|
|
5829
|
+
}
|
|
5830
|
+
__name(confirmTokenExpiry, "confirmTokenExpiry");
|
|
5831
|
+
function verifyConfirmToken(token, subject, options) {
|
|
5832
|
+
if (typeof token !== "string") return false;
|
|
5833
|
+
const expiresAt = confirmTokenExpiry(token);
|
|
5834
|
+
if (expiresAt === void 0 || expiresAt < (options.now ?? Date.now())) return false;
|
|
5835
|
+
const expected = Buffer.from(signature(subject, expiresAt, options.secret));
|
|
5836
|
+
const given = Buffer.from(token.slice(token.indexOf(".") + 1));
|
|
5837
|
+
return expected.length === given.length && timingSafeEqual(expected, given);
|
|
5838
|
+
}
|
|
5839
|
+
__name(verifyConfirmToken, "verifyConfirmToken");
|
|
5840
|
+
function hashConfirmToken(token) {
|
|
5841
|
+
return createHash2("sha256").update(token).digest("hex");
|
|
5842
|
+
}
|
|
5843
|
+
__name(hashConfirmToken, "hashConfirmToken");
|
|
5844
|
+
var InMemoryConfirmTokenStore = class {
|
|
5845
|
+
static {
|
|
5846
|
+
__name(this, "InMemoryConfirmTokenStore");
|
|
5847
|
+
}
|
|
5848
|
+
claims = /* @__PURE__ */ new Map();
|
|
5849
|
+
async claim(input) {
|
|
5850
|
+
await this.purgeExpired();
|
|
5851
|
+
if (this.claims.has(input.hash)) return false;
|
|
5852
|
+
this.claims.set(input.hash, {
|
|
5853
|
+
...input
|
|
5854
|
+
});
|
|
5855
|
+
return true;
|
|
5856
|
+
}
|
|
5857
|
+
async release(hash) {
|
|
5858
|
+
this.claims.delete(hash);
|
|
5859
|
+
}
|
|
5860
|
+
async purgeExpired(now = Date.now()) {
|
|
5861
|
+
let purged = 0;
|
|
5862
|
+
for (const [hash, claim] of this.claims) {
|
|
5863
|
+
if (claim.expiresAt < now) {
|
|
5864
|
+
this.claims.delete(hash);
|
|
5865
|
+
purged += 1;
|
|
5866
|
+
}
|
|
5867
|
+
}
|
|
5868
|
+
return purged;
|
|
5869
|
+
}
|
|
5870
|
+
/** How many tokens are currently marked as spent. */
|
|
5871
|
+
get size() {
|
|
5872
|
+
return this.claims.size;
|
|
5873
|
+
}
|
|
5874
|
+
};
|
|
5875
|
+
|
|
5876
|
+
// src/confirmed-tool.ts
|
|
5877
|
+
var DEFAULT_MESSAGES = {
|
|
5878
|
+
confirm: 'Nothing was written. Show this preview to the user and ask them to confirm. To commit, call this tool again with the SAME arguments plus "confirm": true and this "confirmToken" (valid for {minutes} minutes).',
|
|
5879
|
+
invalid: 'Invalid or expired confirmation: nothing was written. Call the tool without "confirm" to get a fresh preview, then confirm with the "confirmToken" it returns, without changing the arguments.',
|
|
5880
|
+
used: "This preview was already confirmed: nothing was written again. To repeat the operation, ask for a new preview."
|
|
5881
|
+
};
|
|
5882
|
+
var ConfirmTokenError = class extends Error {
|
|
5883
|
+
static {
|
|
5884
|
+
__name(this, "ConfirmTokenError");
|
|
5885
|
+
}
|
|
5886
|
+
reason;
|
|
5887
|
+
constructor(reason, message) {
|
|
5888
|
+
super(message), this.reason = reason;
|
|
5889
|
+
this.name = "ConfirmTokenError";
|
|
5890
|
+
}
|
|
5891
|
+
};
|
|
5892
|
+
var CONFIRM_JSON_SCHEMA_PROPERTIES = {
|
|
5893
|
+
confirm: {
|
|
5894
|
+
type: "boolean",
|
|
5895
|
+
description: "Omit to get a preview (nothing is written). Send true, with confirmToken, to commit."
|
|
5896
|
+
},
|
|
5897
|
+
confirmToken: {
|
|
5898
|
+
type: "string",
|
|
5899
|
+
description: "The confirmToken the preview returned. Required when confirm is true."
|
|
5900
|
+
}
|
|
5901
|
+
};
|
|
5902
|
+
var SCHEMA_EXTENSION = /* @__PURE__ */ Symbol.for("@dudousxd/nestjs-agent:schema-extension");
|
|
5903
|
+
function schemaExtensionOf(schema) {
|
|
5904
|
+
const extension = schema[SCHEMA_EXTENSION];
|
|
5905
|
+
return typeof extension === "object" && extension !== null ? extension : void 0;
|
|
5906
|
+
}
|
|
5907
|
+
__name(schemaExtensionOf, "schemaExtensionOf");
|
|
5908
|
+
function isRecord(value) {
|
|
5909
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5910
|
+
}
|
|
5911
|
+
__name(isRecord, "isRecord");
|
|
5912
|
+
function splitConfirm(input) {
|
|
5913
|
+
if (!isRecord(input)) return {
|
|
5914
|
+
args: input,
|
|
5915
|
+
fields: {}
|
|
5916
|
+
};
|
|
5917
|
+
const { confirm, confirmToken, ...args } = input;
|
|
5918
|
+
return {
|
|
5919
|
+
args,
|
|
5920
|
+
fields: {
|
|
5921
|
+
...typeof confirm === "boolean" ? {
|
|
5922
|
+
confirm
|
|
5923
|
+
} : {},
|
|
5924
|
+
...typeof confirmToken === "string" ? {
|
|
5925
|
+
confirmToken
|
|
5926
|
+
} : {}
|
|
5927
|
+
}
|
|
5928
|
+
};
|
|
5929
|
+
}
|
|
5930
|
+
__name(splitConfirm, "splitConfirm");
|
|
5931
|
+
function jsonSchemaInputOf(schema) {
|
|
5932
|
+
const standard = schema["~standard"];
|
|
5933
|
+
const input = standard.jsonSchema?.input;
|
|
5934
|
+
return typeof input === "function" ? (options) => input.call(standard.jsonSchema, options) : void 0;
|
|
5935
|
+
}
|
|
5936
|
+
__name(jsonSchemaInputOf, "jsonSchemaInputOf");
|
|
5937
|
+
function withConfirmFields(schema) {
|
|
5938
|
+
const inner = schema["~standard"];
|
|
5939
|
+
const innerJsonSchema = jsonSchemaInputOf(schema);
|
|
5940
|
+
const describe = /* @__PURE__ */ __name((options) => {
|
|
5941
|
+
const base = innerJsonSchema?.(options) ?? {
|
|
5942
|
+
additionalProperties: true
|
|
5943
|
+
};
|
|
5944
|
+
return {
|
|
5945
|
+
...base,
|
|
5946
|
+
type: "object",
|
|
5947
|
+
properties: {
|
|
5948
|
+
...isRecord(base.properties) ? base.properties : {},
|
|
5949
|
+
...CONFIRM_JSON_SCHEMA_PROPERTIES
|
|
5950
|
+
}
|
|
5951
|
+
};
|
|
5952
|
+
}, "describe");
|
|
5953
|
+
const wrapped = {
|
|
5954
|
+
[SCHEMA_EXTENSION]: {
|
|
5955
|
+
base: schema,
|
|
5956
|
+
properties: CONFIRM_JSON_SCHEMA_PROPERTIES
|
|
5957
|
+
},
|
|
5958
|
+
"~standard": {
|
|
5959
|
+
version: 1,
|
|
5960
|
+
vendor: "@dudousxd/nestjs-agent",
|
|
5961
|
+
validate: /* @__PURE__ */ __name(async (value) => {
|
|
5962
|
+
if (!isRecord(value)) {
|
|
5963
|
+
return {
|
|
5964
|
+
issues: [
|
|
5965
|
+
{
|
|
5966
|
+
message: "expected an object"
|
|
5967
|
+
}
|
|
5968
|
+
]
|
|
5969
|
+
};
|
|
5970
|
+
}
|
|
5971
|
+
const issues = [];
|
|
5972
|
+
if (value.confirm != null && typeof value.confirm !== "boolean") {
|
|
5973
|
+
issues.push({
|
|
5974
|
+
message: "expected a boolean",
|
|
5975
|
+
path: [
|
|
5976
|
+
"confirm"
|
|
5977
|
+
]
|
|
5978
|
+
});
|
|
5979
|
+
}
|
|
5980
|
+
if (value.confirmToken != null && typeof value.confirmToken !== "string") {
|
|
5981
|
+
issues.push({
|
|
5982
|
+
message: "expected a string",
|
|
5983
|
+
path: [
|
|
5984
|
+
"confirmToken"
|
|
5985
|
+
]
|
|
5986
|
+
});
|
|
5987
|
+
}
|
|
5988
|
+
const { args, fields } = splitConfirm(value);
|
|
5989
|
+
const result = await inner.validate(args);
|
|
5990
|
+
if (result.issues !== void 0) {
|
|
5991
|
+
return {
|
|
5992
|
+
issues: [
|
|
5993
|
+
...issues,
|
|
5994
|
+
...result.issues
|
|
5995
|
+
]
|
|
5996
|
+
};
|
|
5997
|
+
}
|
|
5998
|
+
if (issues.length > 0) {
|
|
5999
|
+
return {
|
|
6000
|
+
issues
|
|
6001
|
+
};
|
|
6002
|
+
}
|
|
6003
|
+
return {
|
|
6004
|
+
value: isRecord(result.value) ? {
|
|
6005
|
+
...result.value,
|
|
6006
|
+
...fields
|
|
6007
|
+
} : result.value
|
|
6008
|
+
};
|
|
6009
|
+
}, "validate"),
|
|
6010
|
+
jsonSchema: {
|
|
6011
|
+
input: describe,
|
|
6012
|
+
output: describe
|
|
6013
|
+
}
|
|
6014
|
+
}
|
|
6015
|
+
};
|
|
6016
|
+
return wrapped;
|
|
6017
|
+
}
|
|
6018
|
+
__name(withConfirmFields, "withConfirmFields");
|
|
6019
|
+
function defineConfirmedTool(options, steps) {
|
|
6020
|
+
const { secret, ttlMs = DEFAULT_CONFIRM_TTL_MS, store, messages, input, ...specFields } = options;
|
|
6021
|
+
const text = {
|
|
6022
|
+
...DEFAULT_MESSAGES,
|
|
6023
|
+
...messages
|
|
6024
|
+
};
|
|
6025
|
+
const howToConfirm = text.confirm.replaceAll("{minutes}", String(Math.round(ttlMs / 6e4)));
|
|
6026
|
+
const secretNow = /* @__PURE__ */ __name(() => typeof secret === "function" ? secret() : secret, "secretNow");
|
|
6027
|
+
const handler = {
|
|
6028
|
+
async execute(value, ctx) {
|
|
6029
|
+
const { args, fields } = splitConfirm(value);
|
|
6030
|
+
const subject = {
|
|
6031
|
+
tool: options.name,
|
|
6032
|
+
actorId: ctx.actor.id,
|
|
6033
|
+
...ctx.actor.tenantRef !== void 0 ? {
|
|
6034
|
+
tenantRef: ctx.actor.tenantRef
|
|
6035
|
+
} : {},
|
|
6036
|
+
args
|
|
6037
|
+
};
|
|
6038
|
+
const confirming = fields.confirm === true;
|
|
6039
|
+
const token = fields.confirmToken;
|
|
6040
|
+
if (confirming && !verifyConfirmToken(token, subject, {
|
|
6041
|
+
secret: secretNow()
|
|
6042
|
+
})) {
|
|
6043
|
+
throw new ConfirmTokenError("invalid", text.invalid);
|
|
6044
|
+
}
|
|
6045
|
+
const prepared = await steps.prepare(args, ctx);
|
|
6046
|
+
if (!confirming || token === void 0) {
|
|
6047
|
+
const preview = await steps.preview(prepared, ctx);
|
|
6048
|
+
const expiresAt = Date.now() + ttlMs;
|
|
6049
|
+
return {
|
|
6050
|
+
status: "preview",
|
|
6051
|
+
summary: preview.summary,
|
|
6052
|
+
...preview.data !== void 0 ? {
|
|
6053
|
+
data: preview.data
|
|
6054
|
+
} : {},
|
|
6055
|
+
confirmToken: signConfirmToken(subject, {
|
|
6056
|
+
secret: secretNow(),
|
|
6057
|
+
expiresAt
|
|
6058
|
+
}),
|
|
6059
|
+
expiresAt: new Date(expiresAt).toISOString(),
|
|
6060
|
+
confirm: howToConfirm
|
|
6061
|
+
};
|
|
6062
|
+
}
|
|
6063
|
+
const hash = hashConfirmToken(token);
|
|
6064
|
+
if (store !== void 0) {
|
|
6065
|
+
const claimed = await store.claim({
|
|
6066
|
+
hash,
|
|
6067
|
+
actorRef: ctx.actor.id,
|
|
6068
|
+
tool: options.name,
|
|
6069
|
+
expiresAt: confirmTokenExpiry(token) ?? Date.now() + ttlMs
|
|
6070
|
+
});
|
|
6071
|
+
if (!claimed) {
|
|
6072
|
+
throw new ConfirmTokenError("used", text.used);
|
|
6073
|
+
}
|
|
6074
|
+
}
|
|
6075
|
+
try {
|
|
6076
|
+
const done = await steps.commit(prepared, ctx);
|
|
6077
|
+
return {
|
|
6078
|
+
status: "done",
|
|
6079
|
+
summary: done.summary,
|
|
6080
|
+
...done.data !== void 0 ? {
|
|
6081
|
+
data: done.data
|
|
6082
|
+
} : {}
|
|
6083
|
+
};
|
|
6084
|
+
} catch (error) {
|
|
6085
|
+
await store?.release(hash).catch(() => void 0);
|
|
6086
|
+
throw error;
|
|
6087
|
+
}
|
|
6088
|
+
}
|
|
6089
|
+
};
|
|
6090
|
+
return {
|
|
6091
|
+
spec: {
|
|
6092
|
+
...specFields,
|
|
6093
|
+
kind: "read",
|
|
6094
|
+
inputSchema: withConfirmFields(input)
|
|
6095
|
+
},
|
|
6096
|
+
handler
|
|
6097
|
+
};
|
|
6098
|
+
}
|
|
6099
|
+
__name(defineConfirmedTool, "defineConfirmedTool");
|
|
5790
6100
|
export {
|
|
5791
6101
|
AGENT_ACTOR_DIRECTORY,
|
|
5792
6102
|
AGENT_ACTOR_RESOLVER,
|
|
5793
6103
|
AGENT_APPROVAL_PORT,
|
|
5794
6104
|
AGENT_ATTACHMENT_STAGING,
|
|
6105
|
+
AGENT_CONFIRM_TOKEN_STORE,
|
|
5795
6106
|
AGENT_DEPS_FACTORY,
|
|
5796
6107
|
AGENT_DIAGNOSTIC_EVENTS,
|
|
5797
6108
|
AGENT_DURABLE_RUNNER,
|
|
@@ -5821,7 +6132,10 @@ export {
|
|
|
5821
6132
|
ASK_TOOL_NAME,
|
|
5822
6133
|
AgentRegistry,
|
|
5823
6134
|
AgentStreamError,
|
|
6135
|
+
CONFIRM_JSON_SCHEMA_PROPERTIES,
|
|
5824
6136
|
ClosedRolesPolicy,
|
|
6137
|
+
ConfirmTokenError,
|
|
6138
|
+
DEFAULT_CONFIRM_TTL_MS,
|
|
5825
6139
|
DEFAULT_HISTORY_SUMMARY_INSTRUCTION,
|
|
5826
6140
|
DEFAULT_INCREMENTAL_LOOKBACK_CHARS,
|
|
5827
6141
|
DEFAULT_INTAKE_PREAMBLE,
|
|
@@ -5837,6 +6151,7 @@ export {
|
|
|
5837
6151
|
ELICITATION_INPUT_TYPES,
|
|
5838
6152
|
GLOBAL_SCOPE,
|
|
5839
6153
|
InMemoryAgentStore,
|
|
6154
|
+
InMemoryConfirmTokenStore,
|
|
5840
6155
|
MAX_ASK_QUESTIONS,
|
|
5841
6156
|
OutputRejectedError,
|
|
5842
6157
|
ProcessorFailedError,
|
|
@@ -5850,6 +6165,7 @@ export {
|
|
|
5850
6165
|
RUN_NOT_ACTIVE_MESSAGE,
|
|
5851
6166
|
RUN_NO_LONGER_RUNNING,
|
|
5852
6167
|
RunCancelledError,
|
|
6168
|
+
SCHEMA_EXTENSION,
|
|
5853
6169
|
SKILL_TOOL_DESCRIPTION,
|
|
5854
6170
|
SKILL_TOOL_NAME,
|
|
5855
6171
|
StructuredOutputError,
|
|
@@ -5872,8 +6188,10 @@ export {
|
|
|
5872
6188
|
buildMemoryBlock,
|
|
5873
6189
|
buildSkillsBlock,
|
|
5874
6190
|
canActorUseTool,
|
|
6191
|
+
canonicalJson,
|
|
5875
6192
|
closeEmptyRoles,
|
|
5876
6193
|
compositeSkillProvider,
|
|
6194
|
+
confirmTokenExpiry,
|
|
5877
6195
|
createFrameBuffer,
|
|
5878
6196
|
createIncrementalGate,
|
|
5879
6197
|
createNoopEmitUi,
|
|
@@ -5883,6 +6201,7 @@ export {
|
|
|
5883
6201
|
decodeStreamEvent,
|
|
5884
6202
|
defaultCanDecide,
|
|
5885
6203
|
defaultScopeResolver,
|
|
6204
|
+
defineConfirmedTool,
|
|
5886
6205
|
detachedDelivered,
|
|
5887
6206
|
detachedStarted,
|
|
5888
6207
|
detachedUnsettled,
|
|
@@ -5899,6 +6218,7 @@ export {
|
|
|
5899
6218
|
findCatalogModel,
|
|
5900
6219
|
gateFollowUps,
|
|
5901
6220
|
gateTail,
|
|
6221
|
+
hashConfirmToken,
|
|
5902
6222
|
invokeWithTransientRetry,
|
|
5903
6223
|
isChatQueueStore,
|
|
5904
6224
|
isControlFlowSignal,
|
|
@@ -5951,12 +6271,14 @@ export {
|
|
|
5951
6271
|
runAgentLoop,
|
|
5952
6272
|
runInputProcessors,
|
|
5953
6273
|
runOutputProcessors,
|
|
6274
|
+
schemaExtensionOf,
|
|
5954
6275
|
seedModelPrices,
|
|
5955
6276
|
settleAll,
|
|
5956
6277
|
settleDanglingToolCalls,
|
|
5957
6278
|
settleDeadRun,
|
|
5958
6279
|
settleElicitation,
|
|
5959
6280
|
settleUnsettledDelegation,
|
|
6281
|
+
signConfirmToken,
|
|
5960
6282
|
skillInputSchema,
|
|
5961
6283
|
skillToolDefinition,
|
|
5962
6284
|
skillWriteVerdict,
|
|
@@ -5975,8 +6297,10 @@ export {
|
|
|
5975
6297
|
validateElicitationAnswer,
|
|
5976
6298
|
validateElicitationValue,
|
|
5977
6299
|
validateStructured,
|
|
6300
|
+
verifyConfirmToken,
|
|
5978
6301
|
windowHistory,
|
|
5979
6302
|
withAskTool,
|
|
6303
|
+
withConfirmFields,
|
|
5980
6304
|
withMemoryTool,
|
|
5981
6305
|
withSelectedModel,
|
|
5982
6306
|
withSkillTool,
|