@standardagents/builder 0.39.1 → 0.40.1

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.
Files changed (43) hide show
  1. package/dist/built-in-routes.js +609 -94
  2. package/dist/built-in-routes.js.map +1 -1
  3. package/dist/client/{ApiKeysView-AH5i-H6j.js → ApiKeysView-DoYvZZ7e.js} +1 -1
  4. package/dist/client/{CenteredContentView-DaBp0K-A.js → CenteredContentView-53PY0cqY.js} +1 -1
  5. package/dist/client/{CompositionView-yY1Q4M23.js → CompositionView-fp-0YnPt.js} +1 -1
  6. package/dist/client/{ConfirmDialog.vue_vue_type_script_setup_true_lang-Bwo5CJzF.js → ConfirmDialog.vue_vue_type_script_setup_true_lang-Cvcagja2.js} +1 -1
  7. package/dist/client/{CopyButton.vue_vue_type_script_setup_true_lang-D0WYwWyA.js → CopyButton.vue_vue_type_script_setup_true_lang-jYvO2v1K.js} +1 -1
  8. package/dist/client/{DataTable.vue_vue_type_script_setup_true_lang-1wwPn2aY.js → DataTable.vue_vue_type_script_setup_true_lang-DQ3Ufa7y.js} +1 -1
  9. package/dist/client/{JsonViewer-Bi8Zdmir.js → JsonViewer-6aaGzutE.js} +1 -1
  10. package/dist/client/{LoginView-BIKahEU6.js → LoginView-DwpCmNw9.js} +1 -1
  11. package/dist/client/{MarketplaceView-DPDPVH68.js → MarketplaceView-Da02L0J5.js} +1 -1
  12. package/dist/client/{Modal.vue_vue_type_script_setup_true_lang-D1_rfOsy.js → Modal.vue_vue_type_script_setup_true_lang-Bi8OjiBf.js} +1 -1
  13. package/dist/client/{ModelModal.vue_vue_type_script_setup_true_lang-DSLeOdxr.js → ModelModal.vue_vue_type_script_setup_true_lang-cYZLOYY7.js} +1 -1
  14. package/dist/client/{ModelsView-Q2WXu1Gw.js → ModelsView-BLlHO9Ud.js} +1 -1
  15. package/dist/client/{PromptEditView-BzA-3n1w.js → PromptEditView-EeNwTDtT.js} +1 -1
  16. package/dist/client/{PromptModal-CJWh_cru.js → PromptModal-BkwrKJ2d.js} +1 -1
  17. package/dist/client/{PromptsView-BezNl-Et.js → PromptsView-D1r7tsLu.js} +1 -1
  18. package/dist/client/{ProvidersView-BuzSKxuT.js → ProvidersView-CmUDl5nM.js} +1 -1
  19. package/dist/client/{ThreadInspectorPane.vue_vue_type_script_setup_true_lang-DOxNp_3C.js → ThreadInspectorPane.vue_vue_type_script_setup_true_lang-cRs3tApQ.js} +1 -1
  20. package/dist/client/{ThreadsView-DPCpZA4J.js → ThreadsView-Bl5fSIO1.js} +1 -1
  21. package/dist/client/{ToolsView-DMjFMAhH.js → ToolsView-DlVEF8-7.js} +1 -1
  22. package/dist/client/{UsersView-B7jXLNQs.js → UsersView-CGlA7a7R.js} +1 -1
  23. package/dist/client/{VariablesView-CF7x0G8g.js → VariablesView-BpYmJL4V.js} +1 -1
  24. package/dist/client/index-CKtIkI0N.js +6 -0
  25. package/dist/client/index.html +1 -1
  26. package/dist/{discovery-DiMJWisl.d.ts → discovery-DZ7fv-b4.d.ts} +3 -2
  27. package/dist/{index-yIcqf7DC.d.ts → index-0NI3m5DR.d.ts} +8 -2
  28. package/dist/index.d.ts +4 -4
  29. package/dist/index.js +1299 -758
  30. package/dist/index.js.map +1 -1
  31. package/dist/packing.d.ts +5 -3
  32. package/dist/packing.js +180 -5
  33. package/dist/packing.js.map +1 -1
  34. package/dist/plugin.d.ts +12 -1
  35. package/dist/plugin.js +299 -19
  36. package/dist/plugin.js.map +1 -1
  37. package/dist/runtime.d.ts +12 -5
  38. package/dist/runtime.js +1009 -750
  39. package/dist/runtime.js.map +1 -1
  40. package/dist/test.d.ts +2 -2
  41. package/dist/{types-Bpe7IANZ.d.ts → types-BMnBYNwn.d.ts} +3 -1
  42. package/package.json +5 -5
  43. package/dist/client/index-eGECJFYe.js +0 -6
package/dist/index.js CHANGED
@@ -6809,6 +6809,547 @@ var init_context = __esm({
6809
6809
  }
6810
6810
  });
6811
6811
 
6812
+ // src/packing/resolver.ts
6813
+ function parseQualifiedName(name) {
6814
+ if (name.startsWith("@")) {
6815
+ const firstSlash = name.indexOf("/");
6816
+ if (firstSlash === -1) {
6817
+ return [null, name];
6818
+ }
6819
+ const secondSlash = name.indexOf("/", firstSlash + 1);
6820
+ if (secondSlash === -1) {
6821
+ return [null, name];
6822
+ }
6823
+ return [name.substring(0, secondSlash), name.substring(secondSlash + 1)];
6824
+ }
6825
+ const separatorIndex = name.indexOf("/");
6826
+ if (separatorIndex === -1) {
6827
+ return [null, name];
6828
+ }
6829
+ return [name.substring(0, separatorIndex), name.substring(separatorIndex + 1)];
6830
+ }
6831
+ function qualifyName(packageId, shortName) {
6832
+ return `${packageId}/${shortName}`;
6833
+ }
6834
+ function getShortName(name) {
6835
+ const [, shortName] = parseQualifiedName(name);
6836
+ return shortName;
6837
+ }
6838
+ function resolveTool(registry, name, namespace) {
6839
+ const [pkgId, shortName] = parseQualifiedName(name);
6840
+ if (pkgId !== null) {
6841
+ const pkg = registry.packages[pkgId];
6842
+ if (!pkg) {
6843
+ throw new NamespaceResolutionError(
6844
+ "tool",
6845
+ name,
6846
+ namespace,
6847
+ `Package "${pkgId}" not found`
6848
+ );
6849
+ }
6850
+ throw new NamespaceResolutionError(
6851
+ "tool",
6852
+ name,
6853
+ namespace,
6854
+ `Cannot access tool "${shortName}" from package "${pkgId}". Only entry point agents are accessible cross-package.`
6855
+ );
6856
+ }
6857
+ if (namespace.type === "packed") {
6858
+ const pkg = registry.packages[namespace.packageId];
6859
+ if (!pkg) {
6860
+ throw new NamespaceResolutionError(
6861
+ "tool",
6862
+ name,
6863
+ namespace,
6864
+ `Package "${namespace.packageId}" not found`
6865
+ );
6866
+ }
6867
+ const loader2 = pkg.tools[shortName];
6868
+ if (!loader2) {
6869
+ throw new NamespaceResolutionError(
6870
+ "tool",
6871
+ name,
6872
+ namespace,
6873
+ `Tool "${shortName}" not found in package "${namespace.packageId}"`
6874
+ );
6875
+ }
6876
+ return loader2;
6877
+ }
6878
+ const loader = registry.global.tools[shortName];
6879
+ if (!loader) {
6880
+ throw new NamespaceResolutionError(
6881
+ "tool",
6882
+ name,
6883
+ namespace,
6884
+ `Tool "${shortName}" not found in global namespace`
6885
+ );
6886
+ }
6887
+ return loader;
6888
+ }
6889
+ function resolvePrompt(registry, name, namespace) {
6890
+ const [pkgId, shortName] = parseQualifiedName(name);
6891
+ if (pkgId !== null) {
6892
+ throw new NamespaceResolutionError(
6893
+ "prompt",
6894
+ name,
6895
+ namespace,
6896
+ `Cannot access prompt "${shortName}" from package "${pkgId}". Prompts are package-internal.`
6897
+ );
6898
+ }
6899
+ if (namespace.type === "packed") {
6900
+ const pkg = registry.packages[namespace.packageId];
6901
+ if (!pkg) {
6902
+ throw new NamespaceResolutionError(
6903
+ "prompt",
6904
+ name,
6905
+ namespace,
6906
+ `Package "${namespace.packageId}" not found`
6907
+ );
6908
+ }
6909
+ const loader2 = pkg.prompts[shortName];
6910
+ if (!loader2) {
6911
+ throw new NamespaceResolutionError(
6912
+ "prompt",
6913
+ name,
6914
+ namespace,
6915
+ `Prompt "${shortName}" not found in package "${namespace.packageId}"`
6916
+ );
6917
+ }
6918
+ return loader2;
6919
+ }
6920
+ const loader = registry.global.prompts[shortName];
6921
+ if (!loader) {
6922
+ throw new NamespaceResolutionError(
6923
+ "prompt",
6924
+ name,
6925
+ namespace,
6926
+ `Prompt "${shortName}" not found in global namespace`
6927
+ );
6928
+ }
6929
+ return loader;
6930
+ }
6931
+ function resolveModel(registry, name, namespace) {
6932
+ const [possiblePkgId, shortName] = parseQualifiedName(name);
6933
+ if (possiblePkgId !== null && registry.packages[possiblePkgId]) {
6934
+ throw new NamespaceResolutionError(
6935
+ "model",
6936
+ name,
6937
+ namespace,
6938
+ `Cannot use qualified model name "${name}". Models must be unqualified. If this is a provider model name, ensure no package named "${possiblePkgId}" exists.`
6939
+ );
6940
+ }
6941
+ const lookupName = name;
6942
+ if (namespace.type === "packed") {
6943
+ const pkg = registry.packages[namespace.packageId];
6944
+ if (pkg) {
6945
+ const loader2 = pkg.models[lookupName];
6946
+ if (loader2) {
6947
+ return loader2;
6948
+ }
6949
+ }
6950
+ const globalLoader = registry.global.models[lookupName];
6951
+ if (globalLoader) {
6952
+ return globalLoader;
6953
+ }
6954
+ throw new NamespaceResolutionError(
6955
+ "model",
6956
+ name,
6957
+ namespace,
6958
+ `Model "${lookupName}" not found in package "${namespace.packageId}" or global namespace`
6959
+ );
6960
+ }
6961
+ const loader = registry.global.models[lookupName];
6962
+ if (!loader) {
6963
+ throw new NamespaceResolutionError(
6964
+ "model",
6965
+ name,
6966
+ namespace,
6967
+ `Model "${lookupName}" not found in global namespace`
6968
+ );
6969
+ }
6970
+ return loader;
6971
+ }
6972
+ function resolveAgent(registry, name, namespace) {
6973
+ const [pkgId, shortName] = parseQualifiedName(name);
6974
+ if (pkgId !== null) {
6975
+ const pkg = registry.packages[pkgId];
6976
+ if (!pkg) {
6977
+ throw new NamespaceResolutionError(
6978
+ "agent",
6979
+ name,
6980
+ namespace,
6981
+ `Package "${pkgId}" not found`
6982
+ );
6983
+ }
6984
+ if (!pkg.entryAgents.includes(shortName)) {
6985
+ throw new NamespaceResolutionError(
6986
+ "agent",
6987
+ name,
6988
+ namespace,
6989
+ `Agent "${shortName}" is not an entry point in package "${pkgId}"`
6990
+ );
6991
+ }
6992
+ const loader = pkg.agents[shortName];
6993
+ if (!loader) {
6994
+ throw new NamespaceResolutionError(
6995
+ "agent",
6996
+ name,
6997
+ namespace,
6998
+ `Agent "${shortName}" not found in package "${pkgId}"`
6999
+ );
7000
+ }
7001
+ return loader;
7002
+ }
7003
+ if (namespace.type === "packed") {
7004
+ const pkg = registry.packages[namespace.packageId];
7005
+ if (!pkg) {
7006
+ throw new NamespaceResolutionError(
7007
+ "agent",
7008
+ name,
7009
+ namespace,
7010
+ `Package "${namespace.packageId}" not found`
7011
+ );
7012
+ }
7013
+ const loader = pkg.agents[shortName];
7014
+ if (!loader) {
7015
+ throw new NamespaceResolutionError(
7016
+ "agent",
7017
+ name,
7018
+ namespace,
7019
+ `Agent "${shortName}" not found in package "${namespace.packageId}"`
7020
+ );
7021
+ }
7022
+ return loader;
7023
+ }
7024
+ const globalLoader = registry.global.agents[shortName];
7025
+ if (globalLoader) {
7026
+ return globalLoader;
7027
+ }
7028
+ for (const [pkgId2, pkg] of Object.entries(registry.packages)) {
7029
+ if (pkg.entryAgents.includes(shortName)) {
7030
+ const loader = pkg.agents[shortName];
7031
+ if (loader) {
7032
+ return loader;
7033
+ }
7034
+ }
7035
+ }
7036
+ throw new NamespaceResolutionError(
7037
+ "agent",
7038
+ name,
7039
+ namespace,
7040
+ `Agent "${shortName}" not found in global namespace`
7041
+ );
7042
+ }
7043
+ function resolveHook(registry, name, namespace) {
7044
+ const [pkgId, shortName] = parseQualifiedName(name);
7045
+ if (pkgId !== null) {
7046
+ throw new NamespaceResolutionError(
7047
+ "hook",
7048
+ name,
7049
+ namespace,
7050
+ `Cannot use qualified hook name "${name}". Hooks must be unqualified.`
7051
+ );
7052
+ }
7053
+ if (namespace.type === "packed") {
7054
+ const pkg = registry.packages[namespace.packageId];
7055
+ if (pkg) {
7056
+ const loader2 = pkg.hooks[shortName];
7057
+ if (loader2) {
7058
+ return loader2;
7059
+ }
7060
+ }
7061
+ return null;
7062
+ }
7063
+ const loader = registry.global.hooks[shortName];
7064
+ return loader || null;
7065
+ }
7066
+ function getVisibleToolNames(registry, namespace) {
7067
+ if (namespace.type === "packed") {
7068
+ const pkg = registry.packages[namespace.packageId];
7069
+ return pkg ? Object.keys(pkg.tools) : [];
7070
+ }
7071
+ return Object.keys(registry.global.tools);
7072
+ }
7073
+ function getVisibleAgentNames(registry, namespace) {
7074
+ if (namespace.type === "packed") {
7075
+ const pkg = registry.packages[namespace.packageId];
7076
+ const ownAgents = pkg ? Object.keys(pkg.agents) : [];
7077
+ const otherEntryPoints = Object.entries(registry.packages).filter(([id]) => id !== namespace.packageId).flatMap(
7078
+ ([pkgId, pkg2]) => pkg2.entryAgents.map((name) => qualifyName(pkgId, name))
7079
+ );
7080
+ return [...ownAgents, ...otherEntryPoints];
7081
+ }
7082
+ const globalAgents = Object.keys(registry.global.agents);
7083
+ const entryPoints = Object.values(registry.packages).flatMap((pkg) => pkg.entryAgents);
7084
+ return [.../* @__PURE__ */ new Set([...globalAgents, ...entryPoints])];
7085
+ }
7086
+ function getVisiblePromptNames(registry, namespace) {
7087
+ if (namespace.type === "packed") {
7088
+ const pkg = registry.packages[namespace.packageId];
7089
+ return pkg ? Object.keys(pkg.prompts) : [];
7090
+ }
7091
+ return Object.keys(registry.global.prompts);
7092
+ }
7093
+ function getVisibleModelNames(registry, namespace) {
7094
+ if (namespace.type === "packed") {
7095
+ const pkg = registry.packages[namespace.packageId];
7096
+ const ownModels = pkg ? Object.keys(pkg.models) : [];
7097
+ const globalModels = Object.keys(registry.global.models);
7098
+ return [.../* @__PURE__ */ new Set([...ownModels, ...globalModels])];
7099
+ }
7100
+ return Object.keys(registry.global.models);
7101
+ }
7102
+ function createNamespaceContext(agentDef) {
7103
+ if (agentDef?.__package) {
7104
+ return { type: "packed", packageId: agentDef.__package.packageId };
7105
+ }
7106
+ return { type: "global" };
7107
+ }
7108
+ function isQualifiedName(name) {
7109
+ if (name.startsWith("@")) {
7110
+ const firstSlash = name.indexOf("/");
7111
+ if (firstSlash === -1) return false;
7112
+ return name.indexOf("/", firstSlash + 1) !== -1;
7113
+ }
7114
+ return name.includes("/");
7115
+ }
7116
+ var NamespaceResolutionError;
7117
+ var init_resolver = __esm({
7118
+ "src/packing/resolver.ts"() {
7119
+ NamespaceResolutionError = class extends Error {
7120
+ constructor(itemType, itemName, namespace, message) {
7121
+ super(message);
7122
+ this.itemType = itemType;
7123
+ this.itemName = itemName;
7124
+ this.namespace = namespace;
7125
+ this.name = "NamespaceResolutionError";
7126
+ }
7127
+ };
7128
+ }
7129
+ });
7130
+
7131
+ // src/agents/ParentHookResolver.ts
7132
+ function packageOf(definition) {
7133
+ return definition?.__package ?? definition?._package;
7134
+ }
7135
+ function qualifyWithinPackage(name, packageId) {
7136
+ if (!packageId || parseQualifiedName(name)[0] !== null) {
7137
+ return name;
7138
+ }
7139
+ return qualifyName(packageId, name);
7140
+ }
7141
+ function promptHooks(prompt) {
7142
+ if (!prompt) return [];
7143
+ return Array.isArray(prompt.hooks) ? prompt.hooks : Array.isArray(prompt._hooks) ? prompt._hooks : [];
7144
+ }
7145
+ function promptTools(prompt) {
7146
+ if (!prompt) return [];
7147
+ return Array.isArray(prompt.tools) ? prompt.tools : Array.isArray(prompt._tools) ? prompt._tools : [];
7148
+ }
7149
+ function relationDescriptor(entry) {
7150
+ if (typeof entry === "string") {
7151
+ return {
7152
+ relationshipName: entry,
7153
+ implementingAgent: entry,
7154
+ explicitlyAgentShaped: false
7155
+ };
7156
+ }
7157
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
7158
+ return null;
7159
+ }
7160
+ const config = entry;
7161
+ if (typeof config.name !== "string" || !config.name) {
7162
+ return null;
7163
+ }
7164
+ const implementingAgent = typeof config.agent === "string" && config.agent ? config.agent : config.name;
7165
+ const explicitlyAgentShaped = "agent" in config || "blocking" in config || "resumable" in config || "immediate" in config || "parentCommunication" in config || "hidden" in config;
7166
+ return {
7167
+ relationshipName: config.name,
7168
+ implementingAgent,
7169
+ optional: typeof config.optional === "string" ? config.optional : void 0,
7170
+ explicitlyAgentShaped
7171
+ };
7172
+ }
7173
+ function hookLoader(host, owner, hookId) {
7174
+ const ownerPackage = packageOf(owner);
7175
+ if (!ownerPackage) {
7176
+ return host.hooks()[hookId];
7177
+ }
7178
+ return host.registry?.()?.packages?.[ownerPackage.packageId]?.hooks?.[hookId];
7179
+ }
7180
+ async function loadBinding(host, owner, hookId, hookType, context, required) {
7181
+ const loader = hookLoader(host, owner, hookId);
7182
+ if (!loader) {
7183
+ if (required) {
7184
+ throw new Error(
7185
+ `Required parent hook '${hookId}' was not found in the child agent namespace`
7186
+ );
7187
+ }
7188
+ return null;
7189
+ }
7190
+ let loaded;
7191
+ try {
7192
+ loaded = await loader();
7193
+ } catch (error) {
7194
+ if (required) throw error;
7195
+ console.error(`[Hooks] Failed to load hook '${hookId}':`, error);
7196
+ return null;
7197
+ }
7198
+ if (!loaded) {
7199
+ if (required) {
7200
+ throw new Error(`Required parent hook '${hookId}' did not export a hook definition`);
7201
+ }
7202
+ return null;
7203
+ }
7204
+ if (typeof loaded.id !== "string" || loaded.id !== hookId) {
7205
+ if (required) {
7206
+ throw new Error(`Required parent hook '${hookId}' exported a mismatched hook ID`);
7207
+ }
7208
+ return null;
7209
+ }
7210
+ if (typeof loaded.execute !== "function") {
7211
+ if (required) {
7212
+ throw new Error(`Required parent hook '${hookId}' did not export an execute function`);
7213
+ }
7214
+ return null;
7215
+ }
7216
+ if (USER_HOOK_NAMES.has(loaded.hook)) {
7217
+ if (required) {
7218
+ throw new Error(
7219
+ `Required parent hook '${hookId}' uses user-scoped hook type '${loaded.hook}'`
7220
+ );
7221
+ }
7222
+ return null;
7223
+ }
7224
+ if (!THREAD_HOOK_NAMES.has(loaded.hook)) {
7225
+ if (required) {
7226
+ throw new Error(`Required parent hook '${hookId}' exported invalid hook type '${loaded.hook}'`);
7227
+ }
7228
+ return null;
7229
+ }
7230
+ if (loaded.hook !== hookType) {
7231
+ return null;
7232
+ }
7233
+ return {
7234
+ id: hookId,
7235
+ hook: hookType,
7236
+ execute: loaded.execute,
7237
+ context
7238
+ };
7239
+ }
7240
+ async function resolveHooksForPrompt(input, hookType) {
7241
+ const agent = input.agent ?? await input.host.loadAgent(input.agentName);
7242
+ const agentPackage = packageOf(agent);
7243
+ const unqualifiedPromptName = input.promptName ?? agent.sideA?.prompt;
7244
+ const resolvedPromptName = unqualifiedPromptName ? qualifyWithinPackage(unqualifiedPromptName, agentPackage?.packageId) : void 0;
7245
+ const prompt = input.prompt ?? (resolvedPromptName ? await input.host.loadPrompt(resolvedPromptName) : void 0);
7246
+ const promptName = prompt?.name ?? prompt?.id ?? resolvedPromptName ?? "unknown_prompt";
7247
+ const before = [];
7248
+ const after = [];
7249
+ for (const entry of promptTools(prompt)) {
7250
+ const relation = relationDescriptor(entry);
7251
+ if (!relation) continue;
7252
+ if (relation.optional && input.isOptionalRelationshipEnabled && !await input.isOptionalRelationshipEnabled(relation.optional)) {
7253
+ continue;
7254
+ }
7255
+ const promptPackage = packageOf(prompt) ?? agentPackage;
7256
+ const childReference = qualifyWithinPackage(
7257
+ relation.implementingAgent,
7258
+ promptPackage?.packageId
7259
+ );
7260
+ let child;
7261
+ try {
7262
+ child = await input.host.loadAgent(childReference);
7263
+ } catch (error) {
7264
+ if (relation.explicitlyAgentShaped) throw error;
7265
+ continue;
7266
+ }
7267
+ if (child.type !== "dual_ai") continue;
7268
+ if (child.parentHooks !== void 0 && child.exposeAsTool !== true) {
7269
+ throw new Error(
7270
+ `Child agent '${childReference}' declares parentHooks but is not exposed as a tool`
7271
+ );
7272
+ }
7273
+ if (child.parentHooks !== void 0 && !Array.isArray(child.parentHooks)) {
7274
+ throw new Error(`Child agent '${childReference}' has an invalid parentHooks declaration`);
7275
+ }
7276
+ const requirements = child.parentHooks ?? [];
7277
+ const seenRequirements = /* @__PURE__ */ new Set();
7278
+ for (const requirement of requirements) {
7279
+ if (!requirement || typeof requirement !== "object" || typeof requirement.hook !== "string" || !requirement.hook || typeof requirement.reason !== "string" || !requirement.reason.trim() || requirement.stage !== void 0 && requirement.stage !== "before_parent" && requirement.stage !== "after_parent" || seenRequirements.has(requirement.hook)) {
7280
+ throw new Error(`Child agent '${childReference}' has an invalid parentHooks requirement`);
7281
+ }
7282
+ seenRequirements.add(requirement.hook);
7283
+ const loaded = await loadBinding(
7284
+ input.host,
7285
+ child,
7286
+ requirement.hook,
7287
+ hookType,
7288
+ {
7289
+ source: {
7290
+ kind: "child",
7291
+ relationshipName: relation.relationshipName,
7292
+ agentName: childReference,
7293
+ package: packageOf(child)
7294
+ }
7295
+ },
7296
+ true
7297
+ );
7298
+ if (!loaded) continue;
7299
+ if ((requirement.stage ?? "after_parent") === "before_parent") {
7300
+ before.push(loaded);
7301
+ } else {
7302
+ after.push(loaded);
7303
+ }
7304
+ }
7305
+ }
7306
+ const promptHookIds = promptHooks(prompt);
7307
+ const promptOwnsBaseHooks = promptHookIds.length > 0 && prompt !== void 0;
7308
+ const baseOwner = promptOwnsBaseHooks ? prompt : agent;
7309
+ const baseIds = promptHookIds.length > 0 ? promptHookIds : Array.isArray(agent.hooks) ? agent.hooks : [];
7310
+ const baseContext = promptOwnsBaseHooks ? { source: { kind: "prompt", promptName } } : { source: { kind: "agent", agentName: input.agentName } };
7311
+ const base = [];
7312
+ for (const hookId of baseIds) {
7313
+ const loaded = await loadBinding(
7314
+ input.host,
7315
+ baseOwner,
7316
+ hookId,
7317
+ hookType,
7318
+ baseContext,
7319
+ false
7320
+ );
7321
+ if (loaded) base.push(loaded);
7322
+ }
7323
+ return [...before, ...base, ...after];
7324
+ }
7325
+ var USER_HOOK_NAMES, THREAD_HOOK_NAMES;
7326
+ var init_ParentHookResolver = __esm({
7327
+ "src/agents/ParentHookResolver.ts"() {
7328
+ init_resolver();
7329
+ USER_HOOK_NAMES = /* @__PURE__ */ new Set([
7330
+ "user_client_attached",
7331
+ "user_client_detached",
7332
+ "user_value_changed"
7333
+ ]);
7334
+ THREAD_HOOK_NAMES = /* @__PURE__ */ new Set([
7335
+ "after_thread_created",
7336
+ "after_subagent_created",
7337
+ "after_system_message",
7338
+ "filter_messages",
7339
+ "prefilter_llm_history",
7340
+ "before_create_message",
7341
+ "after_create_message",
7342
+ "before_update_message",
7343
+ "after_update_message",
7344
+ "before_store_tool_result",
7345
+ "after_tool_call_success",
7346
+ "after_tool_call_failure",
7347
+ "tool_call_started",
7348
+ "tool_call_done"
7349
+ ]);
7350
+ }
7351
+ });
7352
+
6812
7353
  // src/agents/FlowEngine.ts
6813
7354
  var FlowEngine_exports = {};
6814
7355
  __export(FlowEngine_exports, {
@@ -6825,6 +7366,7 @@ var init_FlowEngine = __esm({
6825
7366
  init_context();
6826
7367
  init_sessionTools();
6827
7368
  init_ThreadStateImpl();
7369
+ init_ParentHookResolver();
6828
7370
  IMMEDIATE_BOOTSTRAP_TOOL_NAME = "bootstrap_immediate_subagent";
6829
7371
  HookBlockedExecutionError = class extends Error {
6830
7372
  constructor(message) {
@@ -7167,7 +7709,8 @@ This usually points to something I can't fix from here \u2014 for example the wo
7167
7709
  _variables: def.variables ?? [],
7168
7710
  _env: def.env ?? def.tenvs ?? {},
7169
7711
  _requiredSchema: def.requiredSchema ?? null,
7170
- _hooks: def.hooks ?? []
7712
+ _hooks: def.hooks ?? [],
7713
+ _package: def.__package
7171
7714
  };
7172
7715
  }
7173
7716
  /**
@@ -7557,6 +8100,8 @@ This usually points to something I can't fix from here \u2014 for example the wo
7557
8100
  type: newAgentDef.type,
7558
8101
  created_at: Date.now(),
7559
8102
  max_session_turns: newAgentDef.maxSessionTurns ?? null,
8103
+ hooks: newAgentDef.hooks ?? [],
8104
+ _package: newAgentDef.__package,
7560
8105
  side_a_label: newAgentDef.sideA?.label ?? null,
7561
8106
  side_a_agent_prompt: newAgentDef.sideA?.prompt ?? null,
7562
8107
  side_a_stop_on_response: newAgentDef.sideA?.stopOnResponse ?? true,
@@ -7717,7 +8262,7 @@ This usually points to something I can't fix from here \u2014 for example the wo
7717
8262
  return null;
7718
8263
  }
7719
8264
  return await stub.resolveThreadEnv({
7720
- threadId: state.threadId,
8265
+ threadId: state.thread.metadata.id,
7721
8266
  property,
7722
8267
  promptName: state.prompt?.name
7723
8268
  });
@@ -8239,8 +8784,8 @@ This usually points to something I can't fix from here \u2014 for example the wo
8239
8784
  state.context[key] = existing;
8240
8785
  }
8241
8786
  static async runImmediateToolsIfNeeded(state) {
8242
- const promptTools = Array.isArray(state.prompt._tools) ? state.prompt._tools : [];
8243
- if (promptTools.length === 0) {
8787
+ const promptTools2 = Array.isArray(state.prompt._tools) ? state.prompt._tools : [];
8788
+ if (promptTools2.length === 0) {
8244
8789
  return false;
8245
8790
  }
8246
8791
  if (!state.immediatePromptRuns) {
@@ -8276,7 +8821,7 @@ This usually points to something I can't fix from here \u2014 for example the wo
8276
8821
  (activeInstanceCounts.get(child.name) ?? 0) + 1
8277
8822
  );
8278
8823
  }
8279
- for (const toolConfig of promptTools) {
8824
+ for (const toolConfig of promptTools2) {
8280
8825
  if (!toolConfig || typeof toolConfig !== "object") {
8281
8826
  continue;
8282
8827
  }
@@ -8442,10 +8987,10 @@ This usually points to something I can't fix from here \u2014 for example the wo
8442
8987
  * model's to clean up, and terminate_subagent on an infrastructure child
8443
8988
  * kills work the runtime depends on. Static and pure for direct testing.
8444
8989
  */
8445
- static filterModelVisibleSubagents(registry, promptTools) {
8990
+ static filterModelVisibleSubagents(registry, promptTools2) {
8446
8991
  if (registry.length === 0) return registry;
8447
8992
  const hidden = /* @__PURE__ */ new Set();
8448
- for (const config of promptTools ?? []) {
8993
+ for (const config of promptTools2 ?? []) {
8449
8994
  if (typeof config === "object" && config !== null && "name" in config && config.hidden === true) {
8450
8995
  hidden.add(config.name);
8451
8996
  }
@@ -9475,8 +10020,8 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9475
10020
  try {
9476
10021
  const nativeTools = await this.loadNativeTools(state);
9477
10022
  tools.push(...nativeTools);
9478
- const promptTools = await this.loadPromptTools(state);
9479
- tools.push(...promptTools);
10023
+ const promptTools2 = await this.loadPromptTools(state);
10024
+ tools.push(...promptTools2);
9480
10025
  const agentTools = await this.loadAgentTools(state);
9481
10026
  tools.push(...agentTools);
9482
10027
  const toolNameSources = /* @__PURE__ */ new Map();
@@ -9485,7 +10030,7 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9485
10030
  sources.add("native tool");
9486
10031
  toolNameSources.set(tool.function.name, sources);
9487
10032
  }
9488
- for (const tool of promptTools) {
10033
+ for (const tool of promptTools2) {
9489
10034
  const sources = toolNameSources.get(tool.function.name) || /* @__PURE__ */ new Set();
9490
10035
  sources.add("prompt");
9491
10036
  toolNameSources.set(tool.function.name, sources);
@@ -9627,24 +10172,8 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9627
10172
  // Hook Resolution Helpers
9628
10173
  // ==========================================================================
9629
10174
  /**
9630
- * Get the list of hook IDs that should run for the current context.
9631
- * Resolution: prompt hooks > agent hooks > empty array
9632
- *
9633
- * @param state - Flow state with prompt and agent configuration
9634
- * @returns Array of hook IDs to execute
9635
- */
9636
- static getActiveHookIds(state) {
9637
- if (state.prompt?._hooks !== void 0 && state.prompt._hooks.length > 0) {
9638
- return state.prompt._hooks;
9639
- }
9640
- if (state.agentConfig.hooks !== void 0 && state.agentConfig.hooks.length > 0) {
9641
- return state.agentConfig.hooks;
9642
- }
9643
- return [];
9644
- }
9645
- /**
9646
- * Get hooks of a specific type from the active hook IDs.
9647
- * Returns typed hook executors in the order they appear in the hooks array.
10175
+ * Resolve hooks of a specific type for the active prompt, including required
10176
+ * hooks contributed automatically by its enabled direct child agents.
9648
10177
  *
9649
10178
  * @template K - The hook type name (ensures type-safe executors)
9650
10179
  * @param state - Flow state with hook configuration
@@ -9652,24 +10181,17 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9652
10181
  * @returns Array of typed hook executor functions
9653
10182
  */
9654
10183
  static async getHooksForType(state, hookType) {
9655
- const hookIds = this.getActiveHookIds(state);
9656
- if (hookIds.length === 0) return [];
9657
- const hooksRegistry = state.thread.instance.hooks();
9658
- if (!hooksRegistry) return [];
9659
- const executors = [];
9660
- for (const hookId of hookIds) {
9661
- const hookLoader = hooksRegistry[hookId];
9662
- if (!hookLoader) continue;
9663
- try {
9664
- const hookDef = await hookLoader();
9665
- if (hookDef && hookDef.hook === hookType) {
9666
- executors.push(hookDef.execute);
9667
- }
9668
- } catch (error) {
9669
- console.error(`[Hooks] Failed to load hook '${hookId}':`, error);
9670
- }
9671
- }
9672
- return executors;
10184
+ return await resolveHooksForPrompt(
10185
+ {
10186
+ host: state.thread.instance,
10187
+ agentName: state.agentConfig.id,
10188
+ agent: state.agentConfig,
10189
+ promptName: state.prompt?.id,
10190
+ prompt: state.prompt,
10191
+ isOptionalRelationshipEnabled: (envName) => this.isOptionalToolEnabled(state, envName)
10192
+ },
10193
+ hookType
10194
+ );
9673
10195
  }
9674
10196
  // ==========================================================================
9675
10197
  // Hook Runner Methods
@@ -9687,9 +10209,9 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9687
10209
  if (executors.length === 0) return messages;
9688
10210
  let result = messages;
9689
10211
  const threadState = ThreadStateImpl.fromFlowState(state);
9690
- for (const executor of executors) {
10212
+ for (const { execute, context } of executors) {
9691
10213
  try {
9692
- result = await executor(threadState, result);
10214
+ result = await execute(threadState, result, context);
9693
10215
  } catch (error) {
9694
10216
  if (error && typeof error === "object" && error.block === true) {
9695
10217
  throw new HookBlockedExecutionError(error instanceof Error ? error.message : String(error));
@@ -9707,9 +10229,9 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9707
10229
  if (executors.length === 0) return systemMessage;
9708
10230
  let result = systemMessage;
9709
10231
  const threadState = ThreadStateImpl.fromFlowState(state);
9710
- for (const executor of executors) {
10232
+ for (const { execute, context } of executors) {
9711
10233
  try {
9712
- const next = await executor(threadState, result);
10234
+ const next = await execute(threadState, result, context);
9713
10235
  if (next !== null && next !== void 0) {
9714
10236
  result = next;
9715
10237
  }
@@ -9726,9 +10248,9 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9726
10248
  const executors = await this.getHooksForType(state, "after_subagent_created");
9727
10249
  if (executors.length === 0) return;
9728
10250
  const threadState = ThreadStateImpl.fromFlowState(state);
9729
- for (const executor of executors) {
10251
+ for (const { execute, context } of executors) {
9730
10252
  try {
9731
- await executor(threadState, childState);
10253
+ await execute(threadState, childState, context);
9732
10254
  } catch (error) {
9733
10255
  console.error("[Hooks] \u2717 Error running after_subagent_created hook:", error);
9734
10256
  }
@@ -9747,9 +10269,13 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9747
10269
  if (executors.length === 0) return message;
9748
10270
  let result = message;
9749
10271
  const threadState = threadStateOverride ?? ThreadStateImpl.fromFlowState(state);
9750
- for (const executor of executors) {
10272
+ for (const { execute, context } of executors) {
9751
10273
  try {
9752
- const hooked = await executor(threadState, _FlowEngine.rowToHookMessage(result));
10274
+ const hooked = await execute(
10275
+ threadState,
10276
+ _FlowEngine.rowToHookMessage(result),
10277
+ context
10278
+ );
9753
10279
  result = {
9754
10280
  ...result,
9755
10281
  ...hooked,
@@ -9775,9 +10301,9 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9775
10301
  const executors = await this.getHooksForType(state, "after_create_message");
9776
10302
  if (executors.length === 0) return;
9777
10303
  const threadState = threadStateOverride ?? ThreadStateImpl.fromFlowState(state);
9778
- for (const executor of executors) {
10304
+ for (const { execute, context } of executors) {
9779
10305
  try {
9780
- await executor(threadState, _FlowEngine.rowToHookMessage(message));
10306
+ await execute(threadState, _FlowEngine.rowToHookMessage(message), context);
9781
10307
  } catch (error) {
9782
10308
  console.error("[Hooks] \u2717 Error running after_create_message hook:", error);
9783
10309
  }
@@ -9818,9 +10344,9 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9818
10344
  if (executors.length === 0) return updates;
9819
10345
  let result = updates;
9820
10346
  const threadState = ThreadStateImpl.fromFlowState(state);
9821
- for (const executor of executors) {
10347
+ for (const { execute, context } of executors) {
9822
10348
  try {
9823
- result = await executor(threadState, messageId, result);
10349
+ result = await execute(threadState, messageId, result, context);
9824
10350
  } catch (error) {
9825
10351
  console.error("[Hooks] \u2717 Error running before_update_message hook:", error);
9826
10352
  }
@@ -9838,9 +10364,9 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9838
10364
  const executors = await this.getHooksForType(state, "after_update_message");
9839
10365
  if (executors.length === 0) return;
9840
10366
  const threadState = ThreadStateImpl.fromFlowState(state);
9841
- for (const executor of executors) {
10367
+ for (const { execute, context } of executors) {
9842
10368
  try {
9843
- await executor(threadState, _FlowEngine.rowToHookMessage(message));
10369
+ await execute(threadState, _FlowEngine.rowToHookMessage(message), context);
9844
10370
  } catch (error) {
9845
10371
  console.error("[Hooks] \u2717 Error running after_update_message hook:", error);
9846
10372
  }
@@ -9860,9 +10386,9 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9860
10386
  if (executors.length === 0) return toolResult;
9861
10387
  let result = toolResult;
9862
10388
  const threadState = ThreadStateImpl.fromFlowState(state);
9863
- for (const executor of executors) {
10389
+ for (const { execute, context } of executors) {
9864
10390
  try {
9865
- result = await executor(threadState, toolCall, result);
10391
+ result = await execute(threadState, toolCall, result, context);
9866
10392
  } catch (error) {
9867
10393
  console.error("[Hooks] \u2717 Error running before_store_tool_result hook:", error);
9868
10394
  }
@@ -9882,10 +10408,10 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9882
10408
  if (executors.length === 0) return toolResult;
9883
10409
  let result = toolResult;
9884
10410
  const threadState = ThreadStateImpl.fromFlowState(state);
9885
- for (const executor of executors) {
10411
+ for (const { execute, context } of executors) {
9886
10412
  if (result === null) break;
9887
10413
  try {
9888
- result = await executor(threadState, toolCall, result);
10414
+ result = await execute(threadState, toolCall, result, context);
9889
10415
  } catch (error) {
9890
10416
  console.error("[Hooks] \u2717 Error running after_tool_call_success hook:", error);
9891
10417
  }
@@ -9905,10 +10431,10 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9905
10431
  if (executors.length === 0) return toolResult;
9906
10432
  let result = toolResult;
9907
10433
  const threadState = ThreadStateImpl.fromFlowState(state);
9908
- for (const executor of executors) {
10434
+ for (const { execute, context } of executors) {
9909
10435
  if (result === null) break;
9910
10436
  try {
9911
- result = await executor(threadState, toolCall, result);
10437
+ result = await execute(threadState, toolCall, result, context);
9912
10438
  } catch (error) {
9913
10439
  console.error("[Hooks] \u2717 Error running after_tool_call_failure hook:", error);
9914
10440
  }
@@ -9938,9 +10464,9 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9938
10464
  const executors = await this.getHooksForType(state, "tool_call_started");
9939
10465
  if (executors.length === 0) return;
9940
10466
  const threadState = ThreadStateImpl.fromFlowState(state);
9941
- for (const executor of executors) {
10467
+ for (const { execute, context } of executors) {
9942
10468
  try {
9943
- await executor(threadState, toolCall, progress);
10469
+ await execute(threadState, toolCall, progress, context);
9944
10470
  } catch (error) {
9945
10471
  console.error("[Hooks] \u2717 Error running tool_call_started hook:", error);
9946
10472
  }
@@ -9968,9 +10494,9 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
9968
10494
  const executors = await this.getHooksForType(state, "tool_call_done");
9969
10495
  if (executors.length === 0) return;
9970
10496
  const threadState = ThreadStateImpl.fromFlowState(state);
9971
- for (const executor of executors) {
10497
+ for (const { execute, context } of executors) {
9972
10498
  try {
9973
- await executor(threadState, toolCall, toolResult);
10499
+ await execute(threadState, toolCall, toolResult, context);
9974
10500
  } catch (error) {
9975
10501
  console.error("[Hooks] \u2717 Error running tool_call_done hook:", error);
9976
10502
  }
@@ -10923,12 +11449,12 @@ ${msg.content}` : `${imageDescriptions}${nonImageList}`;
10923
11449
  if (executors.length === 0) return messages;
10924
11450
  let result = messages;
10925
11451
  const threadState = ThreadStateImpl.fromFlowState(state);
10926
- for (const executor of executors) {
11452
+ for (const { execute, context } of executors) {
10927
11453
  try {
10928
11454
  const byId = /* @__PURE__ */ new Map();
10929
11455
  for (const row of result) if (row.id) byId.set(row.id, row);
10930
11456
  const hookView = result.map((row) => _FlowEngine.rowToHookMessage(row));
10931
- const kept = await executor(threadState, hookView);
11457
+ const kept = await execute(threadState, hookView, context);
10932
11458
  result = kept.map((hookedMessage) => {
10933
11459
  const original = hookedMessage.id ? byId.get(hookedMessage.id) : void 0;
10934
11460
  if (original) {
@@ -11175,7 +11701,12 @@ function queueTool(flow, toolName, args = {}) {
11175
11701
  }
11176
11702
  async function injectMessage(flow, options) {
11177
11703
  const messageId = options.id ?? crypto.randomUUID();
11178
- const timestamp = Date.now() * TIMESTAMP_MULTIPLIER;
11704
+ const wallClockTimestamp = Date.now() * TIMESTAMP_MULTIPLIER;
11705
+ const latestLiveTimestamp = flow.messageHistory.reduce(
11706
+ (latest, entry) => Math.max(latest, entry.created_at),
11707
+ 0
11708
+ );
11709
+ const timestamp = options.beforeMessageId ? wallClockTimestamp : Math.max(wallClockTimestamp, latestLiveTimestamp + 1);
11179
11710
  const silent = options.silent ?? false;
11180
11711
  const forceTopLevel = options.forceTopLevel ?? false;
11181
11712
  let message = {
@@ -17013,6 +17544,10 @@ function generateAgentFile(data) {
17013
17544
  if (data.toolDescription) {
17014
17545
  lines.push(` toolDescription: '${escapeString3(data.toolDescription)}',`);
17015
17546
  }
17547
+ if (data.parentHooks && data.parentHooks.length > 0) {
17548
+ const serialized = JSON.stringify(data.parentHooks, null, 2).split("\n").map((line, index) => index === 0 ? line : ` ${line}`).join("\n");
17549
+ lines.push(` parentHooks: ${serialized},`);
17550
+ }
17016
17551
  const env = data.env ?? (data.tenvs || void 0);
17017
17552
  if (env && Object.keys(env).length > 0) {
17018
17553
  lines.push(` env: ${JSON.stringify(env)},`);
@@ -17782,6 +18317,9 @@ function transformAgentData(data) {
17782
18317
  if (data.tool_description) {
17783
18318
  transformed.toolDescription = data.tool_description;
17784
18319
  }
18320
+ if (data.parent_hooks !== void 0 || data.parentHooks !== void 0) {
18321
+ transformed.parentHooks = data.parent_hooks ?? data.parentHooks;
18322
+ }
17785
18323
  if (data.env !== void 0 || data.tenvs !== void 0) {
17786
18324
  transformed.env = normalizeStringEnvRecord(data.env ?? data.tenvs) ?? {};
17787
18325
  }
@@ -18027,6 +18565,22 @@ function validateAgentData(data) {
18027
18565
  if (data.exposeAsTool && !data.toolDescription) {
18028
18566
  errors["tool_description"] = "Tool description is required when expose as tool is enabled";
18029
18567
  }
18568
+ if (data.parentHooks !== void 0) {
18569
+ if (!Array.isArray(data.parentHooks)) {
18570
+ errors["parent_hooks"] = "Parent hooks must be an array";
18571
+ } else if (data.type !== "dual_ai" || !data.exposeAsTool) {
18572
+ errors["parent_hooks"] = "Parent hooks require an exposed dual_ai agent";
18573
+ } else {
18574
+ const seen = /* @__PURE__ */ new Set();
18575
+ for (const requirement of data.parentHooks) {
18576
+ if (!requirement || typeof requirement !== "object" || typeof requirement.hook !== "string" || !requirement.hook || typeof requirement.reason !== "string" || !requirement.reason.trim() || requirement.stage !== void 0 && requirement.stage !== "before_parent" && requirement.stage !== "after_parent" || seen.has(requirement.hook)) {
18577
+ errors["parent_hooks"] = "Parent hook entries require a unique hook, reason, and valid stage";
18578
+ break;
18579
+ }
18580
+ seen.add(requirement.hook);
18581
+ }
18582
+ }
18583
+ }
18030
18584
  if (data.maxSessionTurns !== void 0 && data.maxSessionTurns !== null) {
18031
18585
  if (typeof data.maxSessionTurns !== "number" || data.maxSessionTurns <= 0) {
18032
18586
  errors["max_session_turns"] = "Max session turns must be a positive number";
@@ -18172,6 +18726,44 @@ function discoverPackedPackageDirectories(packedDir) {
18172
18726
  }
18173
18727
  return packageDirs;
18174
18728
  }
18729
+ function discoverStandardAgentPackageDirectories(rootDir) {
18730
+ const packages = /* @__PURE__ */ new Map();
18731
+ const addPackage = (packagePath, source) => {
18732
+ const packageJsonPath = path9__default.join(packagePath, "package.json");
18733
+ if (!fs9__default.existsSync(packageJsonPath)) return;
18734
+ try {
18735
+ const packageJson = JSON.parse(fs9__default.readFileSync(packageJsonPath, "utf8"));
18736
+ if (typeof packageJson.name !== "string" || !Array.isArray(packageJson.standardagent?.entryAgents)) {
18737
+ return;
18738
+ }
18739
+ packages.set(packageJson.name, { path: packagePath, source });
18740
+ } catch {
18741
+ }
18742
+ };
18743
+ const nodeModulesDir = path9__default.join(rootDir, "node_modules");
18744
+ if (fs9__default.existsSync(nodeModulesDir)) {
18745
+ for (const entry of fs9__default.readdirSync(nodeModulesDir, { withFileTypes: true })) {
18746
+ if (entry.name.startsWith(".")) continue;
18747
+ const entryPath = path9__default.join(nodeModulesDir, entry.name);
18748
+ if (entry.name.startsWith("@")) {
18749
+ if (!fs9__default.existsSync(entryPath)) continue;
18750
+ for (const scopedEntry of fs9__default.readdirSync(entryPath, { withFileTypes: true })) {
18751
+ if (!scopedEntry.name.startsWith(".")) {
18752
+ addPackage(path9__default.join(entryPath, scopedEntry.name), "npm");
18753
+ }
18754
+ }
18755
+ } else {
18756
+ addPackage(entryPath, "npm");
18757
+ }
18758
+ }
18759
+ }
18760
+ for (const packagePath of discoverPackedPackageDirectories(
18761
+ path9__default.join(rootDir, "agents", "packed")
18762
+ )) {
18763
+ addPackage(packagePath, "local");
18764
+ }
18765
+ return [...packages.values()];
18766
+ }
18175
18767
  function scanPackedDistDirectory(packagePath, outputDir, subDir) {
18176
18768
  const fullPath = path9__default.join(packagePath, outputDir, subDir);
18177
18769
  if (!fs9__default.existsSync(fullPath)) {
@@ -19115,11 +19707,19 @@ async function extractPromptTools(sourceCode) {
19115
19707
  result.tools.push(element.text);
19116
19708
  } else if (ts.isObjectLiteralExpression(element)) {
19117
19709
  result.hasSubpromptConfigs = true;
19710
+ let configuredName;
19711
+ let implementingAgent;
19118
19712
  for (const objProp of element.properties) {
19119
- if (ts.isPropertyAssignment(objProp) && ts.isIdentifier(objProp.name) && objProp.name.text === "name" && ts.isStringLiteral(objProp.initializer)) {
19120
- result.tools.push(objProp.initializer.text);
19713
+ if (ts.isPropertyAssignment(objProp) && ts.isIdentifier(objProp.name) && ts.isStringLiteral(objProp.initializer)) {
19714
+ if (objProp.name.text === "name") {
19715
+ configuredName = objProp.initializer.text;
19716
+ } else if (objProp.name.text === "agent") {
19717
+ implementingAgent = objProp.initializer.text;
19718
+ }
19121
19719
  }
19122
19720
  }
19721
+ const dependencyName = implementingAgent ?? configuredName;
19722
+ if (dependencyName) result.tools.push(dependencyName);
19123
19723
  }
19124
19724
  }
19125
19725
  }
@@ -19242,6 +19842,106 @@ async function extractAgentPrompts(sourceCode) {
19242
19842
  visit(sourceFile);
19243
19843
  return result;
19244
19844
  }
19845
+ async function extractAgentHooks(sourceCode) {
19846
+ const ts = await loadTypeScript();
19847
+ const sourceFile = ts.createSourceFile(
19848
+ "agent.ts",
19849
+ sourceCode,
19850
+ ts.ScriptTarget.ESNext,
19851
+ true
19852
+ );
19853
+ const arrays = /* @__PURE__ */ new Map();
19854
+ const result = {
19855
+ hooks: [],
19856
+ parentHooks: [],
19857
+ parentHookRequirements: []
19858
+ };
19859
+ const unwrapArray = (expression) => {
19860
+ let current = expression;
19861
+ while (ts.isParenthesizedExpression(current) || ts.isAsExpression(current) || ts.isSatisfiesExpression(current)) {
19862
+ current = current.expression;
19863
+ }
19864
+ if (ts.isArrayLiteralExpression(current)) return current;
19865
+ if (ts.isIdentifier(current)) return arrays.get(current.text) ?? null;
19866
+ return null;
19867
+ };
19868
+ for (const statement of sourceFile.statements) {
19869
+ if (!ts.isVariableStatement(statement)) continue;
19870
+ for (const declaration of statement.declarationList.declarations) {
19871
+ if (ts.isIdentifier(declaration.name) && declaration.initializer) {
19872
+ const array = unwrapArray(declaration.initializer);
19873
+ if (array) arrays.set(declaration.name.text, array);
19874
+ }
19875
+ }
19876
+ }
19877
+ const pushUnique = (target, value) => {
19878
+ if (!target.includes(value)) target.push(value);
19879
+ };
19880
+ function visit(node) {
19881
+ if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "defineAgent" && node.arguments.length > 0 && ts.isObjectLiteralExpression(node.arguments[0])) {
19882
+ for (const property of node.arguments[0].properties) {
19883
+ if (!ts.isPropertyAssignment(property) || !ts.isIdentifier(property.name)) continue;
19884
+ const array = unwrapArray(property.initializer);
19885
+ if (!array) continue;
19886
+ if (property.name.text === "hooks") {
19887
+ for (const element of array.elements) {
19888
+ if (ts.isStringLiteral(element)) pushUnique(result.hooks, element.text);
19889
+ }
19890
+ }
19891
+ if (property.name.text === "parentHooks") {
19892
+ for (const element of array.elements) {
19893
+ if (!ts.isObjectLiteralExpression(element)) continue;
19894
+ let hook;
19895
+ let reason;
19896
+ let stage;
19897
+ for (const requirement of element.properties) {
19898
+ if (ts.isPropertyAssignment(requirement) && ts.isIdentifier(requirement.name) && ts.isStringLiteral(requirement.initializer)) {
19899
+ if (requirement.name.text === "hook") hook = requirement.initializer.text;
19900
+ if (requirement.name.text === "reason") reason = requirement.initializer.text;
19901
+ if (requirement.name.text === "stage" && (requirement.initializer.text === "before_parent" || requirement.initializer.text === "after_parent")) {
19902
+ stage = requirement.initializer.text;
19903
+ }
19904
+ }
19905
+ }
19906
+ if (hook) {
19907
+ pushUnique(result.parentHooks, hook);
19908
+ if (reason) result.parentHookRequirements.push({ hook, reason, stage });
19909
+ }
19910
+ }
19911
+ }
19912
+ }
19913
+ }
19914
+ ts.forEachChild(node, visit);
19915
+ }
19916
+ visit(sourceFile);
19917
+ return result;
19918
+ }
19919
+ async function extractPromptHooks(sourceCode) {
19920
+ const ts = await loadTypeScript();
19921
+ const sourceFile = ts.createSourceFile(
19922
+ "prompt.ts",
19923
+ sourceCode,
19924
+ ts.ScriptTarget.ESNext,
19925
+ true
19926
+ );
19927
+ const hooks = [];
19928
+ function visit(node) {
19929
+ if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "definePrompt" && node.arguments.length > 0 && ts.isObjectLiteralExpression(node.arguments[0])) {
19930
+ for (const property of node.arguments[0].properties) {
19931
+ if (ts.isPropertyAssignment(property) && ts.isIdentifier(property.name) && property.name.text === "hooks" && ts.isArrayLiteralExpression(property.initializer)) {
19932
+ for (const element of property.initializer.elements) {
19933
+ if (ts.isStringLiteral(element) && !hooks.includes(element.text)) {
19934
+ hooks.push(element.text);
19935
+ }
19936
+ }
19937
+ }
19938
+ }
19939
+ }
19940
+ ts.forEachChild(node, visit);
19941
+ }
19942
+ visit(sourceFile);
19943
+ return hooks;
19944
+ }
19245
19945
  async function extractAgentDescription(sourceCode) {
19246
19946
  const ts = await loadTypeScript();
19247
19947
  const sourceFile = ts.createSourceFile(
@@ -19481,6 +20181,13 @@ var PackingService = class {
19481
20181
  });
19482
20182
  const agentSource = fs9.readFileSync(agentFilePath, "utf-8");
19483
20183
  const agentPrompts = await extractAgentPrompts(agentSource);
20184
+ const agentHooks = await extractAgentHooks(agentSource);
20185
+ for (const hookId of agentHooks.hooks) {
20186
+ await this.analyzeHook(hookId, agentsDir, analysis, false, `agent:${agentName}`);
20187
+ }
20188
+ for (const hookId of agentHooks.parentHooks) {
20189
+ await this.analyzeHook(hookId, agentsDir, analysis, true, `agent:${agentName}`);
20190
+ }
19484
20191
  if (agentPrompts.sideA) {
19485
20192
  analysis.primaryPrompt = agentPrompts.sideA;
19486
20193
  await this.analyzePrompt(agentPrompts.sideA, agentsDir, analysis, /* @__PURE__ */ new Set(), `agent:${agentName}`);
@@ -19683,6 +20390,9 @@ var PackingService = class {
19683
20390
  }
19684
20391
  visited.add(`prompt:${promptName}`);
19685
20392
  const promptSource = fs9.readFileSync(promptFilePath, "utf-8");
20393
+ for (const hookId of await extractPromptHooks(promptSource)) {
20394
+ await this.analyzeHook(hookId, agentsDir, analysis, false, thisKey);
20395
+ }
19686
20396
  const modelName = await extractPromptModel(promptSource);
19687
20397
  if (modelName) {
19688
20398
  await this.analyzeModel(modelName, agentsDir, analysis, visited, thisKey);
@@ -19767,6 +20477,13 @@ var PackingService = class {
19767
20477
  visited.add(`agent:${agentName}`);
19768
20478
  const agentSource = fs9.readFileSync(agentFilePath, "utf-8");
19769
20479
  const agentPrompts = await extractAgentPrompts(agentSource);
20480
+ const agentHooks = await extractAgentHooks(agentSource);
20481
+ for (const hookId of agentHooks.hooks) {
20482
+ await this.analyzeHook(hookId, agentsDir, analysis, false, thisKey);
20483
+ }
20484
+ for (const hookId of agentHooks.parentHooks) {
20485
+ await this.analyzeHook(hookId, agentsDir, analysis, true, thisKey);
20486
+ }
19770
20487
  if (agentPrompts.sideA) {
19771
20488
  await this.analyzePrompt(agentPrompts.sideA, agentsDir, analysis, visited, thisKey);
19772
20489
  }
@@ -19774,6 +20491,27 @@ var PackingService = class {
19774
20491
  await this.analyzePrompt(agentPrompts.sideB, agentsDir, analysis, visited, thisKey);
19775
20492
  }
19776
20493
  }
20494
+ /** Add a hook referenced by an agent or prompt to the packed graph. */
20495
+ async analyzeHook(hookId, agentsDir, analysis, required, parentKey) {
20496
+ const hookFilePath = await this.findFile(path9.join(agentsDir, "hooks"), hookId);
20497
+ if (!hookFilePath) {
20498
+ const message = `Hook file not found for ID: ${hookId}`;
20499
+ if (required) analysis.errors.push(message);
20500
+ else analysis.warnings.push(message);
20501
+ return;
20502
+ }
20503
+ if (!analysis.constituents.hooks.some(
20504
+ (hook) => hook.name === hookId && hook.parentKey === parentKey
20505
+ )) {
20506
+ analysis.constituents.hooks.push({
20507
+ name: hookId,
20508
+ filePath: hookFilePath,
20509
+ discoveredVia: "static",
20510
+ sharedWith: [],
20511
+ parentKey
20512
+ });
20513
+ }
20514
+ }
19777
20515
  /**
19778
20516
  * Analyze a model and its fallbacks.
19779
20517
  */
@@ -19908,11 +20646,17 @@ var PackingService = class {
19908
20646
  } = options;
19909
20647
  const finalPackageName = packageName || packageId;
19910
20648
  const packedAt = Date.now();
20649
+ const entryAgentFile = await this.findFile(
20650
+ path9.join(rootDir, "agents", "agents"),
20651
+ agentName
20652
+ );
20653
+ const entryParentHooks = entryAgentFile ? (await extractAgentHooks(fs9.readFileSync(entryAgentFile, "utf-8"))).parentHookRequirements : [];
19911
20654
  const meta = {
19912
20655
  packageId,
19913
20656
  version,
19914
20657
  entryAgents: [agentName],
19915
- packedAt
20658
+ packedAt,
20659
+ ...entryParentHooks.length > 0 ? { parentHooks: { [agentName]: entryParentHooks } } : {}
19916
20660
  };
19917
20661
  const result = {
19918
20662
  success: false,
@@ -20021,6 +20765,7 @@ var PackingService = class {
20021
20765
  agentName,
20022
20766
  this.deduplicateConstituents(analysis).effects.map((effect) => effect.name),
20023
20767
  this.deduplicateConstituents(analysis).threadEndpoints.map((endpoint) => endpoint.name),
20768
+ meta.parentHooks,
20024
20769
  externalDeps,
20025
20770
  rootDir,
20026
20771
  license,
@@ -20412,7 +21157,7 @@ var PackingService = class {
20412
21157
  /**
20413
21158
  * Generate the package.json file with dependencies.
20414
21159
  */
20415
- generatePackageJson(packageName, version, agentName, effects, threadEndpoints, externalDeps, rootDir, license, licenseOwner) {
21160
+ generatePackageJson(packageName, version, agentName, effects, threadEndpoints, parentHooks, externalDeps, rootDir, license, licenseOwner) {
20416
21161
  const dependencies = {
20417
21162
  "@standardagents/spec": this.resolvePackageVersion("@standardagents/spec", rootDir)
20418
21163
  };
@@ -20434,6 +21179,7 @@ var PackingService = class {
20434
21179
  keywords: ["standardagent"],
20435
21180
  standardagent: {
20436
21181
  entryAgents: [agentName],
21182
+ ...parentHooks ? { parentHooks } : {},
20437
21183
  ...effects.length > 0 ? { effects } : {},
20438
21184
  ...threadEndpoints.length > 0 ? { threadEndpoints } : {}
20439
21185
  },
@@ -20727,6 +21473,22 @@ ${license || "See LICENSE file"}
20727
21473
  return agents;
20728
21474
  }
20729
21475
  };
21476
+ function validParentHooks(value) {
21477
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
21478
+ return Object.values(value).every((requirements) => {
21479
+ if (!Array.isArray(requirements)) return false;
21480
+ const seen = /* @__PURE__ */ new Set();
21481
+ return requirements.every((requirement) => {
21482
+ if (typeof requirement !== "object" || requirement === null) return false;
21483
+ const item = requirement;
21484
+ if (typeof item.hook !== "string" || !item.hook.trim() || typeof item.reason !== "string" || !item.reason.trim() || item.stage !== void 0 && item.stage !== "before_parent" && item.stage !== "after_parent" || seen.has(item.hook)) {
21485
+ return false;
21486
+ }
21487
+ seen.add(item.hook);
21488
+ return true;
21489
+ });
21490
+ });
21491
+ }
20730
21492
  var PackageDiscoveryService = class {
20731
21493
  config;
20732
21494
  constructor(config) {
@@ -20822,6 +21584,7 @@ var PackageDiscoveryService = class {
20822
21584
  }
20823
21585
  const effects = Array.isArray(pkgJson.standardagent.effects) && pkgJson.standardagent.effects.every((effectName) => typeof effectName === "string") ? pkgJson.standardagent.effects : void 0;
20824
21586
  const threadEndpoints = Array.isArray(pkgJson.standardagent.threadEndpoints) && pkgJson.standardagent.threadEndpoints.every((endpoint) => typeof endpoint === "string") ? pkgJson.standardagent.threadEndpoints : void 0;
21587
+ const parentHooks = validParentHooks(pkgJson.standardagent.parentHooks) ? pkgJson.standardagent.parentHooks : void 0;
20825
21588
  return {
20826
21589
  packageId: pkgJson.name || pkgName,
20827
21590
  version: pkgJson.version || "0.0.0",
@@ -20830,6 +21593,7 @@ var PackageDiscoveryService = class {
20830
21593
  entryAgents: pkgJson.standardagent.entryAgents,
20831
21594
  ...effects ? { effects } : {},
20832
21595
  ...threadEndpoints ? { threadEndpoints } : {},
21596
+ ...parentHooks ? { parentHooks } : {},
20833
21597
  description: pkgJson.description
20834
21598
  };
20835
21599
  } catch (error) {
@@ -20891,6 +21655,7 @@ var PackageDiscoveryService = class {
20891
21655
  }
20892
21656
  const effects = Array.isArray(pkgJson.standardagent.effects) && pkgJson.standardagent.effects.every((effectName) => typeof effectName === "string") ? pkgJson.standardagent.effects : void 0;
20893
21657
  const threadEndpoints = Array.isArray(pkgJson.standardagent.threadEndpoints) && pkgJson.standardagent.threadEndpoints.every((endpoint) => typeof endpoint === "string") ? pkgJson.standardagent.threadEndpoints : void 0;
21658
+ const parentHooks = validParentHooks(pkgJson.standardagent.parentHooks) ? pkgJson.standardagent.parentHooks : void 0;
20894
21659
  return {
20895
21660
  packageId: pkgJson.name || dirName,
20896
21661
  version: pkgJson.version || "0.0.0",
@@ -20899,6 +21664,7 @@ var PackageDiscoveryService = class {
20899
21664
  entryAgents: pkgJson.standardagent.entryAgents,
20900
21665
  ...effects ? { effects } : {},
20901
21666
  ...threadEndpoints ? { threadEndpoints } : {},
21667
+ ...parentHooks ? { parentHooks } : {},
20902
21668
  description: pkgJson.description
20903
21669
  };
20904
21670
  } catch (error) {
@@ -20927,7 +21693,8 @@ var PackageDiscoveryService = class {
20927
21693
  const hasValidEntryAgents = Array.isArray(f.entryAgents) && f.entryAgents.length > 0 && f.entryAgents.every((e) => typeof e === "string");
20928
21694
  const hasValidEffects = f.effects === void 0 || Array.isArray(f.effects) && f.effects.every((effectName) => typeof effectName === "string");
20929
21695
  const hasValidThreadEndpoints = f.threadEndpoints === void 0 || Array.isArray(f.threadEndpoints) && f.threadEndpoints.every((endpoint) => typeof endpoint === "string");
20930
- return hasValidEntryAgents && hasValidEffects && hasValidThreadEndpoints;
21696
+ const hasValidParentHooks = f.parentHooks === void 0 || validParentHooks(f.parentHooks);
21697
+ return hasValidEntryAgents && hasValidEffects && hasValidThreadEndpoints && hasValidParentHooks;
20931
21698
  }
20932
21699
  /**
20933
21700
  * Get a package by ID.
@@ -22555,13 +23322,13 @@ async function loadRegistryVirtualModule(context) {
22555
23322
  const absPath = toAbsolutePath(importPath);
22556
23323
  return ` "${name}": async () => (await import("${absPath}")).default,`;
22557
23324
  }).join("\n");
22558
- const packedDir = path9__default.resolve(process.cwd(), "agents/packed");
23325
+ const projectRoot = process.cwd();
22559
23326
  const packedPackages = [];
22560
- if (fs9__default.existsSync(packedDir)) {
22561
- console.log(`[vite-plugin-agent] Scanning packed directory: ${packedDir}`);
22562
- const packageDirs = discoverPackedPackageDirectories(packedDir);
22563
- console.log(`[vite-plugin-agent] Found package dirs: ${packageDirs.join(", ")}`);
22564
- for (const pkgPath of packageDirs) {
23327
+ {
23328
+ const packageDirs = discoverStandardAgentPackageDirectories(projectRoot);
23329
+ console.log(`[vite-plugin-agent] Found Standard Agent package dirs: ${packageDirs.map((pkg) => pkg.path).join(", ")}`);
23330
+ for (const discovered of packageDirs) {
23331
+ const pkgPath = discovered.path;
22565
23332
  const pkgJsonPath = path9__default.join(pkgPath, "package.json");
22566
23333
  if (fs9__default.existsSync(pkgJsonPath)) {
22567
23334
  try {
@@ -22575,6 +23342,7 @@ async function loadRegistryVirtualModule(context) {
22575
23342
  const pkg = {
22576
23343
  packageId: pkgJson.name,
22577
23344
  version: pkgJson.version,
23345
+ source: discovered.source,
22578
23346
  entryAgents: pkgJson.standardagent.entryAgents || [],
22579
23347
  items: {
22580
23348
  agents: scanPackedDistDirectory(pkgPath, outputDir, "agents"),
@@ -22593,15 +23361,13 @@ async function loadRegistryVirtualModule(context) {
22593
23361
  }
22594
23362
  }
22595
23363
  }
22596
- } else {
22597
- console.log(`[vite-plugin-agent] Packed directory does not exist: ${packedDir}`);
22598
23364
  }
22599
23365
  console.log(`[vite-plugin-agent] Total packed packages found: ${packedPackages.length}`);
22600
23366
  const packagesCode = packedPackages.map((pkg) => {
22601
23367
  const signature = JSON.stringify({
22602
23368
  packageId: pkg.packageId,
22603
23369
  version: pkg.version,
22604
- source: "local",
23370
+ source: pkg.source,
22605
23371
  packedAt: Date.now()
22606
23372
  });
22607
23373
  const genLoaders = (items) => items.map(
@@ -22700,9 +23466,9 @@ async function loadRoutesVirtualModule(context) {
22700
23466
  );`;
22701
23467
  }).join("\n");
22702
23468
  const packedThreadRoutes = [];
22703
- const packedDir = path9__default.resolve(process.cwd(), "agents/packed");
22704
- const packedPackageDirs = discoverPackedPackageDirectories(packedDir);
22705
- for (const packagePath of packedPackageDirs) {
23469
+ const packedPackageDirs = discoverStandardAgentPackageDirectories(process.cwd());
23470
+ for (const discovered of packedPackageDirs) {
23471
+ const packagePath = discovered.path;
22706
23472
  const packageJsonPath = path9__default.join(packagePath, "package.json");
22707
23473
  if (!fs9__default.existsSync(packageJsonPath)) {
22708
23474
  continue;
@@ -23062,7 +23828,8 @@ async function loadVirtualModule(id, context) {
23062
23828
  effectsDir,
23063
23829
  installedProviders,
23064
23830
  rou3Code,
23065
- hmr
23831
+ hmr,
23832
+ deviceApproval
23066
23833
  } = context;
23067
23834
  if (id === RESOLVED_VIRTUAL_TOOLS_ID) {
23068
23835
  const tools = await scanToolsDirectory(toolsDir);
@@ -23126,6 +23893,7 @@ export const config = {
23126
23893
  providersDir: "${relativeProvidersDir}",
23127
23894
  promptsDir: "${relativePromptsDir}",
23128
23895
  agentsDir: "${relativeAgentsDir}",
23896
+ deviceApproval: ${JSON.stringify(deviceApproval ?? null)},
23129
23897
  };`;
23130
23898
  }
23131
23899
  if (id === RESOLVED_VIRTUAL_MODELS_ID) {
@@ -23485,8 +24253,50 @@ function applyPluginEnvironmentConfig(config) {
23485
24253
  }
23486
24254
  }
23487
24255
 
24256
+ // src/plugin/device-approval.ts
24257
+ function requiredText(value, field, maxLength) {
24258
+ if (typeof value !== "string" || !value.trim() || value.trim().length > maxLength) {
24259
+ throw new Error(`deviceApproval.${field} must be a non-empty string of ${maxLength} characters or fewer`);
24260
+ }
24261
+ return value.trim();
24262
+ }
24263
+ function optionalText(value, field, maxLength) {
24264
+ if (value === void 0 || value === null || value === "") return void 0;
24265
+ if (typeof value !== "string" || !value.trim() || value.trim().length > maxLength) {
24266
+ throw new Error(`deviceApproval.${field} must be a string of ${maxLength} characters or fewer`);
24267
+ }
24268
+ return value.trim();
24269
+ }
24270
+ function safeLogoUrl(value) {
24271
+ const logoUrl = optionalText(value, "logoUrl", 2048);
24272
+ if (!logoUrl) return void 0;
24273
+ if (logoUrl.startsWith("/") && !logoUrl.startsWith("//") && !logoUrl.includes("#") && !logoUrl.includes("\\")) {
24274
+ return logoUrl;
24275
+ }
24276
+ try {
24277
+ const parsed = new URL(logoUrl);
24278
+ if (parsed.protocol !== "https:" || parsed.username || parsed.password || parsed.hash) throw new Error();
24279
+ return parsed.toString();
24280
+ } catch {
24281
+ throw new Error("deviceApproval.logoUrl must be a safe HTTPS or root-relative URL");
24282
+ }
24283
+ }
24284
+ function normalizeDeviceApprovalBrand(value) {
24285
+ if (value === void 0) return void 0;
24286
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
24287
+ throw new Error("deviceApproval must be an object");
24288
+ }
24289
+ const normalized = { name: requiredText(value.name, "name", 100) };
24290
+ const description = optionalText(value.description, "description", 280);
24291
+ const logoUrl = safeLogoUrl(value.logoUrl);
24292
+ if (description) normalized.description = description;
24293
+ if (logoUrl) normalized.logoUrl = logoUrl;
24294
+ return normalized;
24295
+ }
24296
+
23488
24297
  // src/plugin.ts
23489
24298
  function agentbuilder(options = {}) {
24299
+ const deviceApproval = normalizeDeviceApprovalBrand(options.deviceApproval);
23490
24300
  const toolsDir = options.toolsDir ? path9__default.resolve(process.cwd(), options.toolsDir) : path9__default.resolve(process.cwd(), "agents/tools");
23491
24301
  const hooksDir = options.hooksDir ? path9__default.resolve(process.cwd(), options.hooksDir) : path9__default.resolve(process.cwd(), "agents/hooks");
23492
24302
  const threadApiDir = options.apiDir ? path9__default.resolve(process.cwd(), options.apiDir) : path9__default.resolve(process.cwd(), "agents/api");
@@ -23577,7 +24387,8 @@ export { CodeExecutionBridge, DurableAgentBuilder, DurableThread, ThreadWatchdog
23577
24387
  effectsDir,
23578
24388
  installedProviders,
23579
24389
  rou3Code,
23580
- hmr
24390
+ hmr,
24391
+ deviceApproval
23581
24392
  };
23582
24393
  const devMiddlewareContext = {
23583
24394
  toolsDir,
@@ -26182,694 +26993,381 @@ var migration48 = {
26182
26993
  platform_user_id, email, display_name, avatar_url, instance_role,
26183
26994
  source, replica_active, replica_updated_at, deleted_at, permissions
26184
26995
  )
26185
- SELECT
26186
- id, username, password_hash, role, created_at, updated_at,
26187
- platform_user_id, email, display_name, avatar_url, instance_role,
26188
- source, replica_active, replica_updated_at, deleted_at, permissions
26189
- FROM users_0012_old
26190
- `);
26191
- sql.exec(`DROP TABLE users_0012_old`);
26192
- sql.exec(`CREATE INDEX idx_users_username ON users(username)`);
26193
- sql.exec(`CREATE INDEX idx_users_role ON users(role)`);
26194
- sql.exec(`CREATE INDEX idx_users_platform_user_id ON users(platform_user_id)`);
26195
- sql.exec(`CREATE INDEX idx_users_replica_active ON users(replica_active)`);
26196
- sql.exec(`CREATE INDEX idx_users_instance_role ON users(instance_role)`);
26197
- sql.exec(`
26198
- CREATE TABLE oauth_accounts (
26199
- id TEXT PRIMARY KEY NOT NULL,
26200
- user_id TEXT NOT NULL,
26201
- provider TEXT NOT NULL CHECK (provider IN ('github', 'google')),
26202
- provider_user_id TEXT NOT NULL,
26203
- provider_username TEXT,
26204
- created_at INTEGER DEFAULT (strftime('%s', 'now')),
26205
- FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
26206
- )
26207
- `);
26208
- sql.exec(`INSERT INTO oauth_accounts SELECT * FROM oauth_accounts_0012_backup`);
26209
- sql.exec(`CREATE UNIQUE INDEX idx_oauth_accounts_provider ON oauth_accounts(provider, provider_user_id)`);
26210
- sql.exec(`CREATE INDEX idx_oauth_accounts_user_id ON oauth_accounts(user_id)`);
26211
- sql.exec(`
26212
- CREATE TABLE api_keys (
26213
- id TEXT PRIMARY KEY NOT NULL,
26214
- name TEXT NOT NULL,
26215
- key_hash TEXT NOT NULL,
26216
- key_prefix TEXT NOT NULL,
26217
- last_five TEXT NOT NULL,
26218
- user_id TEXT NOT NULL,
26219
- created_at INTEGER DEFAULT (strftime('%s', 'now')),
26220
- last_used_at INTEGER,
26221
- platform_key_id TEXT,
26222
- scope TEXT,
26223
- source TEXT NOT NULL DEFAULT 'local' CHECK (source IN ('local', 'standard_agents')),
26224
- replica_active INTEGER NOT NULL DEFAULT 1,
26225
- replica_updated_at INTEGER,
26226
- FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
26227
- )
26228
- `);
26229
- sql.exec(`INSERT INTO api_keys SELECT * FROM api_keys_0012_backup`);
26230
- sql.exec(`CREATE INDEX idx_api_keys_key_hash ON api_keys(key_hash)`);
26231
- sql.exec(`CREATE INDEX idx_api_keys_user_id ON api_keys(user_id)`);
26232
- sql.exec(`CREATE INDEX idx_api_keys_key_prefix ON api_keys(key_prefix)`);
26233
- sql.exec(`CREATE INDEX idx_api_keys_platform_key_id ON api_keys(platform_key_id)`);
26234
- sql.exec(`CREATE INDEX idx_api_keys_replica_active ON api_keys(replica_active)`);
26235
- sql.exec(`
26236
- CREATE TABLE sessions (
26237
- id TEXT PRIMARY KEY NOT NULL,
26238
- user_id TEXT NOT NULL,
26239
- token_hash TEXT NOT NULL,
26240
- expires_at INTEGER NOT NULL,
26241
- created_at INTEGER DEFAULT (strftime('%s', 'now')),
26242
- FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
26243
- )
26244
- `);
26245
- sql.exec(`INSERT INTO sessions SELECT * FROM sessions_0012_backup`);
26246
- sql.exec(`CREATE INDEX idx_sessions_token_hash ON sessions(token_hash)`);
26247
- sql.exec(`CREATE INDEX idx_sessions_user_id ON sessions(user_id)`);
26248
- sql.exec(`CREATE INDEX idx_sessions_expires_at ON sessions(expires_at)`);
26249
- sql.exec(`DROP TABLE oauth_accounts_0012_backup`);
26250
- sql.exec(`DROP TABLE api_keys_0012_backup`);
26251
- sql.exec(`DROP TABLE sessions_0012_backup`);
26252
- sql.exec(`
26253
- INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '12')
26254
- `);
26255
- }
26256
- };
26257
-
26258
- // src/durable-objects/agentbuilder-migrations/0013_add_thread_activity.ts
26259
- var migration49 = {
26260
- version: 13,
26261
- async up(sql) {
26262
- sql.exec(`ALTER TABLE threads ADD COLUMN last_activity_at INTEGER`);
26263
- sql.exec(`ALTER TABLE threads ADD COLUMN executing_since INTEGER`);
26264
- sql.exec(
26265
- `CREATE INDEX IF NOT EXISTS idx_threads_last_activity_at ON threads(last_activity_at)`
26266
- );
26267
- sql.exec(`UPDATE threads SET last_activity_at = created_at`);
26268
- sql.exec(`
26269
- INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '13')
26270
- `);
26271
- }
26272
- };
26273
-
26274
- // src/durable-objects/agentbuilder-migrations/0014_thread_activity_scale.ts
26275
- var migration50 = {
26276
- version: 14,
26277
- async up(sql) {
26278
- sql.exec(`ALTER TABLE threads ADD COLUMN last_message_preview TEXT`);
26279
- sql.exec(
26280
- `CREATE INDEX IF NOT EXISTS idx_threads_executing_since
26281
- ON threads(executing_since) WHERE executing_since IS NOT NULL`
26282
- );
26283
- sql.exec(
26284
- `UPDATE threads SET last_activity_at = created_at WHERE last_activity_at IS NULL`
26285
- );
26286
- sql.exec(`
26287
- INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '14')
26288
- `);
26289
- }
26290
- };
26291
-
26292
- // src/durable-objects/agentbuilder-migrations/0015_clear_envelope_previews.ts
26293
- var migration51 = {
26294
- version: 15,
26295
- async up(sql) {
26296
- sql.exec(
26297
- `UPDATE threads SET last_message_preview = NULL
26298
- WHERE last_message_preview LIKE 'Subagent (reference: %'`
26299
- );
26300
- sql.exec(`
26301
- INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '15')
26302
- `);
26303
- }
26304
- };
26305
-
26306
- // src/durable-objects/agentbuilder-migrations/0016_add_origin_agent.ts
26307
- var migration52 = {
26308
- version: 16,
26309
- async up(sql) {
26310
- sql.exec(`ALTER TABLE threads ADD COLUMN origin_agent_name TEXT`);
26311
- sql.exec(
26312
- `CREATE INDEX IF NOT EXISTS idx_threads_origin_agent_name ON threads(origin_agent_name)`
26313
- );
26314
- sql.exec(`UPDATE threads SET origin_agent_name = agent_name`);
26315
- sql.exec(`
26316
- INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '16')
26317
- `);
26318
- }
26319
- };
26320
-
26321
- // src/durable-objects/agentbuilder-migrations/0017_add_thread_message_recency.ts
26322
- var migration53 = {
26323
- version: 17,
26324
- async up(sql) {
26325
- sql.exec(`ALTER TABLE threads ADD COLUMN last_message_at INTEGER`);
26326
- sql.exec(`UPDATE threads SET last_message_at = created_at`);
26327
- sql.exec(`
26328
- INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '17')
26329
- `);
26330
- }
26331
- };
26332
-
26333
- // src/durable-objects/agentbuilder-migrations/0018_auth_security.ts
26334
- var migration54 = {
26335
- version: 18,
26336
- async up(sql) {
26337
- sql.exec(`
26338
- CREATE TABLE IF NOT EXISTS super_admin_sessions (
26339
- token_hash TEXT PRIMARY KEY,
26340
- created_at INTEGER NOT NULL,
26341
- expires_at INTEGER NOT NULL
26342
- )
26343
- `);
26344
- sql.exec(`
26345
- CREATE INDEX IF NOT EXISTS idx_super_admin_sessions_expires
26346
- ON super_admin_sessions(expires_at)
26347
- `);
26348
- sql.exec(`
26349
- CREATE TABLE IF NOT EXISTS auth_rate_limits (
26350
- bucket_key TEXT PRIMARY KEY,
26351
- attempts INTEGER NOT NULL,
26352
- reset_at INTEGER NOT NULL
26353
- )
26354
- `);
26355
- sql.exec(`
26356
- CREATE INDEX IF NOT EXISTS idx_auth_rate_limits_reset
26357
- ON auth_rate_limits(reset_at)
26358
- `);
26359
- sql.exec(`
26360
- INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '18')
26361
- `);
26362
- }
26363
- };
26364
-
26365
- // src/durable-objects/agentbuilder-migrations/0019_scope_skills.ts
26366
- var migration55 = {
26367
- version: 19,
26368
- async up(sql) {
26369
- sql.exec(`
26370
- CREATE TABLE skills_0019 (
26371
- owner_id TEXT NOT NULL,
26372
- name TEXT NOT NULL,
26373
- description TEXT NOT NULL,
26374
- version TEXT,
26375
- enabled INTEGER NOT NULL DEFAULT 1,
26376
- shared INTEGER NOT NULL DEFAULT 0,
26377
- created_at INTEGER DEFAULT (strftime('%s', 'now')),
26378
- updated_at INTEGER DEFAULT (strftime('%s', 'now')),
26379
- PRIMARY KEY (owner_id, name)
26380
- )
26381
- `);
26382
- sql.exec(`
26383
- INSERT INTO skills_0019 (
26384
- owner_id, name, description, version, enabled, shared, created_at, updated_at
26385
- )
26386
- SELECT '__instance_shared__', name, description, version, enabled, 1, created_at, updated_at
26387
- FROM skills
26388
- `);
26389
- sql.exec(`
26390
- CREATE TABLE skill_files_0019 (
26391
- owner_id TEXT NOT NULL,
26392
- skill_name TEXT NOT NULL,
26393
- path TEXT NOT NULL,
26394
- content TEXT NOT NULL,
26395
- size INTEGER NOT NULL,
26396
- PRIMARY KEY (owner_id, skill_name, path),
26397
- FOREIGN KEY (owner_id, skill_name) REFERENCES skills_0019(owner_id, name) ON DELETE CASCADE
26398
- )
26399
- `);
26400
- sql.exec(`
26401
- INSERT INTO skill_files_0019 (owner_id, skill_name, path, content, size)
26402
- SELECT '__instance_shared__', skill_name, path, content, size FROM skill_files
26403
- `);
26404
- sql.exec(`DROP TABLE skill_files`);
26405
- sql.exec(`DROP TABLE skills`);
26406
- sql.exec(`ALTER TABLE skills_0019 RENAME TO skills`);
26407
- sql.exec(`ALTER TABLE skill_files_0019 RENAME TO skill_files`);
26408
- sql.exec(`CREATE INDEX idx_skills_owner_enabled ON skills(owner_id, enabled)`);
26409
- sql.exec(`CREATE INDEX idx_skills_shared_enabled ON skills(shared, enabled)`);
26410
- sql.exec(`CREATE INDEX idx_skill_files_skill ON skill_files(owner_id, skill_name)`);
26411
- sql.exec(`INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '19')`);
26412
- }
26413
- };
26414
-
26415
- // src/durable-objects/agentbuilder-migrations/0020_websocket_tickets.ts
26416
- var migration56 = {
26417
- version: 20,
26418
- async up(sql) {
26996
+ SELECT
26997
+ id, username, password_hash, role, created_at, updated_at,
26998
+ platform_user_id, email, display_name, avatar_url, instance_role,
26999
+ source, replica_active, replica_updated_at, deleted_at, permissions
27000
+ FROM users_0012_old
27001
+ `);
27002
+ sql.exec(`DROP TABLE users_0012_old`);
27003
+ sql.exec(`CREATE INDEX idx_users_username ON users(username)`);
27004
+ sql.exec(`CREATE INDEX idx_users_role ON users(role)`);
27005
+ sql.exec(`CREATE INDEX idx_users_platform_user_id ON users(platform_user_id)`);
27006
+ sql.exec(`CREATE INDEX idx_users_replica_active ON users(replica_active)`);
27007
+ sql.exec(`CREATE INDEX idx_users_instance_role ON users(instance_role)`);
26419
27008
  sql.exec(`
26420
- CREATE TABLE websocket_tickets (
26421
- ticket_hash TEXT PRIMARY KEY,
26422
- pathname TEXT NOT NULL,
26423
- auth_json TEXT NOT NULL,
26424
- created_at INTEGER NOT NULL,
26425
- expires_at INTEGER NOT NULL
27009
+ CREATE TABLE oauth_accounts (
27010
+ id TEXT PRIMARY KEY NOT NULL,
27011
+ user_id TEXT NOT NULL,
27012
+ provider TEXT NOT NULL CHECK (provider IN ('github', 'google')),
27013
+ provider_user_id TEXT NOT NULL,
27014
+ provider_username TEXT,
27015
+ created_at INTEGER DEFAULT (strftime('%s', 'now')),
27016
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
26426
27017
  )
26427
27018
  `);
27019
+ sql.exec(`INSERT INTO oauth_accounts SELECT * FROM oauth_accounts_0012_backup`);
27020
+ sql.exec(`CREATE UNIQUE INDEX idx_oauth_accounts_provider ON oauth_accounts(provider, provider_user_id)`);
27021
+ sql.exec(`CREATE INDEX idx_oauth_accounts_user_id ON oauth_accounts(user_id)`);
26428
27022
  sql.exec(`
26429
- CREATE INDEX idx_websocket_tickets_expires
26430
- ON websocket_tickets(expires_at)
27023
+ CREATE TABLE api_keys (
27024
+ id TEXT PRIMARY KEY NOT NULL,
27025
+ name TEXT NOT NULL,
27026
+ key_hash TEXT NOT NULL,
27027
+ key_prefix TEXT NOT NULL,
27028
+ last_five TEXT NOT NULL,
27029
+ user_id TEXT NOT NULL,
27030
+ created_at INTEGER DEFAULT (strftime('%s', 'now')),
27031
+ last_used_at INTEGER,
27032
+ platform_key_id TEXT,
27033
+ scope TEXT,
27034
+ source TEXT NOT NULL DEFAULT 'local' CHECK (source IN ('local', 'standard_agents')),
27035
+ replica_active INTEGER NOT NULL DEFAULT 1,
27036
+ replica_updated_at INTEGER,
27037
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
27038
+ )
26431
27039
  `);
26432
- sql.exec(`INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '20')`);
26433
- }
26434
- };
26435
-
26436
- // src/durable-objects/agentbuilder-migrations/0021_platform_handoff_jtis.ts
26437
- var migration57 = {
26438
- version: 21,
26439
- async up(sql) {
27040
+ sql.exec(`INSERT INTO api_keys SELECT * FROM api_keys_0012_backup`);
27041
+ sql.exec(`CREATE INDEX idx_api_keys_key_hash ON api_keys(key_hash)`);
27042
+ sql.exec(`CREATE INDEX idx_api_keys_user_id ON api_keys(user_id)`);
27043
+ sql.exec(`CREATE INDEX idx_api_keys_key_prefix ON api_keys(key_prefix)`);
27044
+ sql.exec(`CREATE INDEX idx_api_keys_platform_key_id ON api_keys(platform_key_id)`);
27045
+ sql.exec(`CREATE INDEX idx_api_keys_replica_active ON api_keys(replica_active)`);
26440
27046
  sql.exec(`
26441
- CREATE TABLE platform_handoff_jtis (
26442
- jti TEXT PRIMARY KEY,
26443
- consumed_at INTEGER NOT NULL,
26444
- expires_at INTEGER NOT NULL
27047
+ CREATE TABLE sessions (
27048
+ id TEXT PRIMARY KEY NOT NULL,
27049
+ user_id TEXT NOT NULL,
27050
+ token_hash TEXT NOT NULL,
27051
+ expires_at INTEGER NOT NULL,
27052
+ created_at INTEGER DEFAULT (strftime('%s', 'now')),
27053
+ FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
26445
27054
  )
26446
27055
  `);
27056
+ sql.exec(`INSERT INTO sessions SELECT * FROM sessions_0012_backup`);
27057
+ sql.exec(`CREATE INDEX idx_sessions_token_hash ON sessions(token_hash)`);
27058
+ sql.exec(`CREATE INDEX idx_sessions_user_id ON sessions(user_id)`);
27059
+ sql.exec(`CREATE INDEX idx_sessions_expires_at ON sessions(expires_at)`);
27060
+ sql.exec(`DROP TABLE oauth_accounts_0012_backup`);
27061
+ sql.exec(`DROP TABLE api_keys_0012_backup`);
27062
+ sql.exec(`DROP TABLE sessions_0012_backup`);
26447
27063
  sql.exec(`
26448
- CREATE INDEX idx_platform_handoff_jtis_expires
26449
- ON platform_handoff_jtis(expires_at)
27064
+ INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '12')
26450
27065
  `);
26451
- sql.exec(`INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '21')`);
26452
- }
26453
- };
26454
-
26455
- // src/durable-objects/agentbuilder-migrations/index.ts
26456
- var migrations2 = [migration37, migration38, migration39, migration40, migration41, migration42, migration43, migration44, migration45, migration46, migration47, migration48, migration49, migration50, migration51, migration52, migration53, migration54, migration55, migration56, migration57];
26457
- var LATEST_SCHEMA_VERSION2 = migrations2.reduce(
26458
- (max, migration58) => Math.max(max, migration58.version),
26459
- 0
26460
- );
26461
-
26462
- // src/utils/crypto.ts
26463
- var CryptoUtil = class {
26464
- static algorithm = "aes-256-gcm";
26465
- /**
26466
- * Encrypt a string value
26467
- */
26468
- static async encrypt(text, key) {
26469
- const encoder = new TextEncoder();
26470
- const data = encoder.encode(text);
26471
- const cryptoKey = await crypto.subtle.importKey(
26472
- "raw",
26473
- hexToBuffer(key),
26474
- { name: "AES-GCM" },
26475
- false,
26476
- ["encrypt"]
26477
- );
26478
- const iv = crypto.getRandomValues(new Uint8Array(12));
26479
- const encrypted = await crypto.subtle.encrypt(
26480
- {
26481
- name: "AES-GCM",
26482
- iv
26483
- },
26484
- cryptoKey,
26485
- data
26486
- );
26487
- const combined = new Uint8Array(iv.length + encrypted.byteLength);
26488
- combined.set(iv);
26489
- combined.set(new Uint8Array(encrypted), iv.length);
26490
- return bufferToBase64(combined);
26491
- }
26492
- /**
26493
- * Decrypt a string value
26494
- */
26495
- static async decrypt(encryptedText, key) {
26496
- const combined = base64ToBuffer2(encryptedText);
26497
- const iv = combined.slice(0, 12);
26498
- const encrypted = combined.slice(12);
26499
- const cryptoKey = await crypto.subtle.importKey(
26500
- "raw",
26501
- hexToBuffer(key),
26502
- { name: "AES-GCM" },
26503
- false,
26504
- ["decrypt"]
26505
- );
26506
- const decrypted = await crypto.subtle.decrypt(
26507
- {
26508
- name: "AES-GCM",
26509
- iv
26510
- },
26511
- cryptoKey,
26512
- encrypted
26513
- );
26514
- const decoder = new TextDecoder();
26515
- return decoder.decode(decrypted);
26516
- }
26517
- };
26518
- function hexToBuffer(hex) {
26519
- const bytes = new Uint8Array(hex.length / 2);
26520
- for (let i = 0; i < hex.length; i += 2) {
26521
- bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
26522
- }
26523
- return bytes;
26524
- }
26525
- function bufferToBase64(buffer) {
26526
- let binary = "";
26527
- for (let i = 0; i < buffer.byteLength; i++) {
26528
- binary += String.fromCharCode(buffer[i]);
26529
- }
26530
- return btoa(binary);
26531
- }
26532
- function base64ToBuffer2(base64) {
26533
- const binary = atob(base64);
26534
- const bytes = new Uint8Array(binary.length);
26535
- for (let i = 0; i < binary.length; i++) {
26536
- bytes[i] = binary.charCodeAt(i);
26537
- }
26538
- return bytes;
26539
- }
26540
- async function encryptEnvs(env, encryptionKey) {
26541
- const plaintext = JSON.stringify(env);
26542
- return CryptoUtil.encrypt(plaintext, encryptionKey);
26543
- }
26544
- async function decryptEnvs(encrypted, encryptionKey) {
26545
- const plaintext = await CryptoUtil.decrypt(encrypted, encryptionKey);
26546
- const parsed = JSON.parse(plaintext);
26547
- if (!parsed || typeof parsed !== "object") {
26548
- return {};
26549
- }
26550
- const result = {};
26551
- for (const [key, value] of Object.entries(parsed)) {
26552
- if (value === void 0 || value === null) continue;
26553
- result[key] = String(value);
26554
- }
26555
- return result;
26556
- }
26557
-
26558
- // src/packing/resolver.ts
26559
- var NamespaceResolutionError = class extends Error {
26560
- constructor(itemType, itemName, namespace, message) {
26561
- super(message);
26562
- this.itemType = itemType;
26563
- this.itemName = itemName;
26564
- this.namespace = namespace;
26565
- this.name = "NamespaceResolutionError";
26566
- }
26567
- };
26568
- function parseQualifiedName(name) {
26569
- if (name.startsWith("@")) {
26570
- const firstSlash = name.indexOf("/");
26571
- if (firstSlash === -1) {
26572
- return [null, name];
26573
- }
26574
- const secondSlash = name.indexOf("/", firstSlash + 1);
26575
- if (secondSlash === -1) {
26576
- return [null, name];
26577
- }
26578
- return [name.substring(0, secondSlash), name.substring(secondSlash + 1)];
26579
- }
26580
- const separatorIndex = name.indexOf("/");
26581
- if (separatorIndex === -1) {
26582
- return [null, name];
26583
- }
26584
- return [name.substring(0, separatorIndex), name.substring(separatorIndex + 1)];
26585
- }
26586
- function qualifyName(packageId, shortName) {
26587
- return `${packageId}/${shortName}`;
26588
- }
26589
- function getShortName(name) {
26590
- const [, shortName] = parseQualifiedName(name);
26591
- return shortName;
26592
- }
26593
- function resolveTool(registry, name, namespace) {
26594
- const [pkgId, shortName] = parseQualifiedName(name);
26595
- if (pkgId !== null) {
26596
- const pkg = registry.packages[pkgId];
26597
- if (!pkg) {
26598
- throw new NamespaceResolutionError(
26599
- "tool",
26600
- name,
26601
- namespace,
26602
- `Package "${pkgId}" not found`
26603
- );
26604
- }
26605
- throw new NamespaceResolutionError(
26606
- "tool",
26607
- name,
26608
- namespace,
26609
- `Cannot access tool "${shortName}" from package "${pkgId}". Only entry point agents are accessible cross-package.`
26610
- );
26611
- }
26612
- if (namespace.type === "packed") {
26613
- const pkg = registry.packages[namespace.packageId];
26614
- if (!pkg) {
26615
- throw new NamespaceResolutionError(
26616
- "tool",
26617
- name,
26618
- namespace,
26619
- `Package "${namespace.packageId}" not found`
26620
- );
26621
- }
26622
- const loader2 = pkg.tools[shortName];
26623
- if (!loader2) {
26624
- throw new NamespaceResolutionError(
26625
- "tool",
26626
- name,
26627
- namespace,
26628
- `Tool "${shortName}" not found in package "${namespace.packageId}"`
26629
- );
26630
- }
26631
- return loader2;
26632
27066
  }
26633
- const loader = registry.global.tools[shortName];
26634
- if (!loader) {
26635
- throw new NamespaceResolutionError(
26636
- "tool",
26637
- name,
26638
- namespace,
26639
- `Tool "${shortName}" not found in global namespace`
27067
+ };
27068
+
27069
+ // src/durable-objects/agentbuilder-migrations/0013_add_thread_activity.ts
27070
+ var migration49 = {
27071
+ version: 13,
27072
+ async up(sql) {
27073
+ sql.exec(`ALTER TABLE threads ADD COLUMN last_activity_at INTEGER`);
27074
+ sql.exec(`ALTER TABLE threads ADD COLUMN executing_since INTEGER`);
27075
+ sql.exec(
27076
+ `CREATE INDEX IF NOT EXISTS idx_threads_last_activity_at ON threads(last_activity_at)`
26640
27077
  );
27078
+ sql.exec(`UPDATE threads SET last_activity_at = created_at`);
27079
+ sql.exec(`
27080
+ INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '13')
27081
+ `);
26641
27082
  }
26642
- return loader;
26643
- }
26644
- function resolvePrompt(registry, name, namespace) {
26645
- const [pkgId, shortName] = parseQualifiedName(name);
26646
- if (pkgId !== null) {
26647
- throw new NamespaceResolutionError(
26648
- "prompt",
26649
- name,
26650
- namespace,
26651
- `Cannot access prompt "${shortName}" from package "${pkgId}". Prompts are package-internal.`
27083
+ };
27084
+
27085
+ // src/durable-objects/agentbuilder-migrations/0014_thread_activity_scale.ts
27086
+ var migration50 = {
27087
+ version: 14,
27088
+ async up(sql) {
27089
+ sql.exec(`ALTER TABLE threads ADD COLUMN last_message_preview TEXT`);
27090
+ sql.exec(
27091
+ `CREATE INDEX IF NOT EXISTS idx_threads_executing_since
27092
+ ON threads(executing_since) WHERE executing_since IS NOT NULL`
26652
27093
  );
26653
- }
26654
- if (namespace.type === "packed") {
26655
- const pkg = registry.packages[namespace.packageId];
26656
- if (!pkg) {
26657
- throw new NamespaceResolutionError(
26658
- "prompt",
26659
- name,
26660
- namespace,
26661
- `Package "${namespace.packageId}" not found`
26662
- );
26663
- }
26664
- const loader2 = pkg.prompts[shortName];
26665
- if (!loader2) {
26666
- throw new NamespaceResolutionError(
26667
- "prompt",
26668
- name,
26669
- namespace,
26670
- `Prompt "${shortName}" not found in package "${namespace.packageId}"`
26671
- );
26672
- }
26673
- return loader2;
26674
- }
26675
- const loader = registry.global.prompts[shortName];
26676
- if (!loader) {
26677
- throw new NamespaceResolutionError(
26678
- "prompt",
26679
- name,
26680
- namespace,
26681
- `Prompt "${shortName}" not found in global namespace`
27094
+ sql.exec(
27095
+ `UPDATE threads SET last_activity_at = created_at WHERE last_activity_at IS NULL`
26682
27096
  );
27097
+ sql.exec(`
27098
+ INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '14')
27099
+ `);
26683
27100
  }
26684
- return loader;
26685
- }
26686
- function resolveModel(registry, name, namespace) {
26687
- const [possiblePkgId, shortName] = parseQualifiedName(name);
26688
- if (possiblePkgId !== null && registry.packages[possiblePkgId]) {
26689
- throw new NamespaceResolutionError(
26690
- "model",
26691
- name,
26692
- namespace,
26693
- `Cannot use qualified model name "${name}". Models must be unqualified. If this is a provider model name, ensure no package named "${possiblePkgId}" exists.`
27101
+ };
27102
+
27103
+ // src/durable-objects/agentbuilder-migrations/0015_clear_envelope_previews.ts
27104
+ var migration51 = {
27105
+ version: 15,
27106
+ async up(sql) {
27107
+ sql.exec(
27108
+ `UPDATE threads SET last_message_preview = NULL
27109
+ WHERE last_message_preview LIKE 'Subagent (reference: %'`
26694
27110
  );
27111
+ sql.exec(`
27112
+ INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '15')
27113
+ `);
26695
27114
  }
26696
- const lookupName = name;
26697
- if (namespace.type === "packed") {
26698
- const pkg = registry.packages[namespace.packageId];
26699
- if (pkg) {
26700
- const loader2 = pkg.models[lookupName];
26701
- if (loader2) {
26702
- return loader2;
26703
- }
26704
- }
26705
- const globalLoader = registry.global.models[lookupName];
26706
- if (globalLoader) {
26707
- return globalLoader;
26708
- }
26709
- throw new NamespaceResolutionError(
26710
- "model",
26711
- name,
26712
- namespace,
26713
- `Model "${lookupName}" not found in package "${namespace.packageId}" or global namespace`
27115
+ };
27116
+
27117
+ // src/durable-objects/agentbuilder-migrations/0016_add_origin_agent.ts
27118
+ var migration52 = {
27119
+ version: 16,
27120
+ async up(sql) {
27121
+ sql.exec(`ALTER TABLE threads ADD COLUMN origin_agent_name TEXT`);
27122
+ sql.exec(
27123
+ `CREATE INDEX IF NOT EXISTS idx_threads_origin_agent_name ON threads(origin_agent_name)`
26714
27124
  );
27125
+ sql.exec(`UPDATE threads SET origin_agent_name = agent_name`);
27126
+ sql.exec(`
27127
+ INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '16')
27128
+ `);
26715
27129
  }
26716
- const loader = registry.global.models[lookupName];
26717
- if (!loader) {
26718
- throw new NamespaceResolutionError(
26719
- "model",
26720
- name,
26721
- namespace,
26722
- `Model "${lookupName}" not found in global namespace`
26723
- );
27130
+ };
27131
+
27132
+ // src/durable-objects/agentbuilder-migrations/0017_add_thread_message_recency.ts
27133
+ var migration53 = {
27134
+ version: 17,
27135
+ async up(sql) {
27136
+ sql.exec(`ALTER TABLE threads ADD COLUMN last_message_at INTEGER`);
27137
+ sql.exec(`UPDATE threads SET last_message_at = created_at`);
27138
+ sql.exec(`
27139
+ INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '17')
27140
+ `);
26724
27141
  }
26725
- return loader;
26726
- }
26727
- function resolveAgent(registry, name, namespace) {
26728
- const [pkgId, shortName] = parseQualifiedName(name);
26729
- if (pkgId !== null) {
26730
- const pkg = registry.packages[pkgId];
26731
- if (!pkg) {
26732
- throw new NamespaceResolutionError(
26733
- "agent",
26734
- name,
26735
- namespace,
26736
- `Package "${pkgId}" not found`
26737
- );
26738
- }
26739
- if (!pkg.entryAgents.includes(shortName)) {
26740
- throw new NamespaceResolutionError(
26741
- "agent",
26742
- name,
26743
- namespace,
26744
- `Agent "${shortName}" is not an entry point in package "${pkgId}"`
26745
- );
26746
- }
26747
- const loader = pkg.agents[shortName];
26748
- if (!loader) {
26749
- throw new NamespaceResolutionError(
26750
- "agent",
26751
- name,
26752
- namespace,
26753
- `Agent "${shortName}" not found in package "${pkgId}"`
26754
- );
26755
- }
26756
- return loader;
27142
+ };
27143
+
27144
+ // src/durable-objects/agentbuilder-migrations/0018_auth_security.ts
27145
+ var migration54 = {
27146
+ version: 18,
27147
+ async up(sql) {
27148
+ sql.exec(`
27149
+ CREATE TABLE IF NOT EXISTS super_admin_sessions (
27150
+ token_hash TEXT PRIMARY KEY,
27151
+ created_at INTEGER NOT NULL,
27152
+ expires_at INTEGER NOT NULL
27153
+ )
27154
+ `);
27155
+ sql.exec(`
27156
+ CREATE INDEX IF NOT EXISTS idx_super_admin_sessions_expires
27157
+ ON super_admin_sessions(expires_at)
27158
+ `);
27159
+ sql.exec(`
27160
+ CREATE TABLE IF NOT EXISTS auth_rate_limits (
27161
+ bucket_key TEXT PRIMARY KEY,
27162
+ attempts INTEGER NOT NULL,
27163
+ reset_at INTEGER NOT NULL
27164
+ )
27165
+ `);
27166
+ sql.exec(`
27167
+ CREATE INDEX IF NOT EXISTS idx_auth_rate_limits_reset
27168
+ ON auth_rate_limits(reset_at)
27169
+ `);
27170
+ sql.exec(`
27171
+ INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '18')
27172
+ `);
26757
27173
  }
26758
- if (namespace.type === "packed") {
26759
- const pkg = registry.packages[namespace.packageId];
26760
- if (!pkg) {
26761
- throw new NamespaceResolutionError(
26762
- "agent",
26763
- name,
26764
- namespace,
26765
- `Package "${namespace.packageId}" not found`
26766
- );
26767
- }
26768
- const loader = pkg.agents[shortName];
26769
- if (!loader) {
26770
- throw new NamespaceResolutionError(
26771
- "agent",
26772
- name,
26773
- namespace,
26774
- `Agent "${shortName}" not found in package "${namespace.packageId}"`
26775
- );
26776
- }
26777
- return loader;
27174
+ };
27175
+
27176
+ // src/durable-objects/agentbuilder-migrations/0019_scope_skills.ts
27177
+ var migration55 = {
27178
+ version: 19,
27179
+ async up(sql) {
27180
+ sql.exec(`
27181
+ CREATE TABLE skills_0019 (
27182
+ owner_id TEXT NOT NULL,
27183
+ name TEXT NOT NULL,
27184
+ description TEXT NOT NULL,
27185
+ version TEXT,
27186
+ enabled INTEGER NOT NULL DEFAULT 1,
27187
+ shared INTEGER NOT NULL DEFAULT 0,
27188
+ created_at INTEGER DEFAULT (strftime('%s', 'now')),
27189
+ updated_at INTEGER DEFAULT (strftime('%s', 'now')),
27190
+ PRIMARY KEY (owner_id, name)
27191
+ )
27192
+ `);
27193
+ sql.exec(`
27194
+ INSERT INTO skills_0019 (
27195
+ owner_id, name, description, version, enabled, shared, created_at, updated_at
27196
+ )
27197
+ SELECT '__instance_shared__', name, description, version, enabled, 1, created_at, updated_at
27198
+ FROM skills
27199
+ `);
27200
+ sql.exec(`
27201
+ CREATE TABLE skill_files_0019 (
27202
+ owner_id TEXT NOT NULL,
27203
+ skill_name TEXT NOT NULL,
27204
+ path TEXT NOT NULL,
27205
+ content TEXT NOT NULL,
27206
+ size INTEGER NOT NULL,
27207
+ PRIMARY KEY (owner_id, skill_name, path),
27208
+ FOREIGN KEY (owner_id, skill_name) REFERENCES skills_0019(owner_id, name) ON DELETE CASCADE
27209
+ )
27210
+ `);
27211
+ sql.exec(`
27212
+ INSERT INTO skill_files_0019 (owner_id, skill_name, path, content, size)
27213
+ SELECT '__instance_shared__', skill_name, path, content, size FROM skill_files
27214
+ `);
27215
+ sql.exec(`DROP TABLE skill_files`);
27216
+ sql.exec(`DROP TABLE skills`);
27217
+ sql.exec(`ALTER TABLE skills_0019 RENAME TO skills`);
27218
+ sql.exec(`ALTER TABLE skill_files_0019 RENAME TO skill_files`);
27219
+ sql.exec(`CREATE INDEX idx_skills_owner_enabled ON skills(owner_id, enabled)`);
27220
+ sql.exec(`CREATE INDEX idx_skills_shared_enabled ON skills(shared, enabled)`);
27221
+ sql.exec(`CREATE INDEX idx_skill_files_skill ON skill_files(owner_id, skill_name)`);
27222
+ sql.exec(`INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '19')`);
26778
27223
  }
26779
- const globalLoader = registry.global.agents[shortName];
26780
- if (globalLoader) {
26781
- return globalLoader;
27224
+ };
27225
+
27226
+ // src/durable-objects/agentbuilder-migrations/0020_websocket_tickets.ts
27227
+ var migration56 = {
27228
+ version: 20,
27229
+ async up(sql) {
27230
+ sql.exec(`
27231
+ CREATE TABLE websocket_tickets (
27232
+ ticket_hash TEXT PRIMARY KEY,
27233
+ pathname TEXT NOT NULL,
27234
+ auth_json TEXT NOT NULL,
27235
+ created_at INTEGER NOT NULL,
27236
+ expires_at INTEGER NOT NULL
27237
+ )
27238
+ `);
27239
+ sql.exec(`
27240
+ CREATE INDEX idx_websocket_tickets_expires
27241
+ ON websocket_tickets(expires_at)
27242
+ `);
27243
+ sql.exec(`INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '20')`);
26782
27244
  }
26783
- for (const [pkgId2, pkg] of Object.entries(registry.packages)) {
26784
- if (pkg.entryAgents.includes(shortName)) {
26785
- const loader = pkg.agents[shortName];
26786
- if (loader) {
26787
- return loader;
26788
- }
26789
- }
27245
+ };
27246
+
27247
+ // src/durable-objects/agentbuilder-migrations/0021_platform_handoff_jtis.ts
27248
+ var migration57 = {
27249
+ version: 21,
27250
+ async up(sql) {
27251
+ sql.exec(`
27252
+ CREATE TABLE platform_handoff_jtis (
27253
+ jti TEXT PRIMARY KEY,
27254
+ consumed_at INTEGER NOT NULL,
27255
+ expires_at INTEGER NOT NULL
27256
+ )
27257
+ `);
27258
+ sql.exec(`
27259
+ CREATE INDEX idx_platform_handoff_jtis_expires
27260
+ ON platform_handoff_jtis(expires_at)
27261
+ `);
27262
+ sql.exec(`INSERT OR REPLACE INTO _metadata (key, value) VALUES ('schema_version', '21')`);
26790
27263
  }
26791
- throw new NamespaceResolutionError(
26792
- "agent",
26793
- name,
26794
- namespace,
26795
- `Agent "${shortName}" not found in global namespace`
26796
- );
26797
- }
26798
- function resolveHook(registry, name, namespace) {
26799
- const [pkgId, shortName] = parseQualifiedName(name);
26800
- if (pkgId !== null) {
26801
- throw new NamespaceResolutionError(
26802
- "hook",
26803
- name,
26804
- namespace,
26805
- `Cannot use qualified hook name "${name}". Hooks must be unqualified.`
27264
+ };
27265
+
27266
+ // src/durable-objects/agentbuilder-migrations/index.ts
27267
+ var migrations2 = [migration37, migration38, migration39, migration40, migration41, migration42, migration43, migration44, migration45, migration46, migration47, migration48, migration49, migration50, migration51, migration52, migration53, migration54, migration55, migration56, migration57];
27268
+ var LATEST_SCHEMA_VERSION2 = migrations2.reduce(
27269
+ (max, migration58) => Math.max(max, migration58.version),
27270
+ 0
27271
+ );
27272
+
27273
+ // src/utils/crypto.ts
27274
+ var CryptoUtil = class {
27275
+ static algorithm = "aes-256-gcm";
27276
+ /**
27277
+ * Encrypt a string value
27278
+ */
27279
+ static async encrypt(text, key) {
27280
+ const encoder = new TextEncoder();
27281
+ const data = encoder.encode(text);
27282
+ const cryptoKey = await crypto.subtle.importKey(
27283
+ "raw",
27284
+ hexToBuffer(key),
27285
+ { name: "AES-GCM" },
27286
+ false,
27287
+ ["encrypt"]
27288
+ );
27289
+ const iv = crypto.getRandomValues(new Uint8Array(12));
27290
+ const encrypted = await crypto.subtle.encrypt(
27291
+ {
27292
+ name: "AES-GCM",
27293
+ iv
27294
+ },
27295
+ cryptoKey,
27296
+ data
26806
27297
  );
27298
+ const combined = new Uint8Array(iv.length + encrypted.byteLength);
27299
+ combined.set(iv);
27300
+ combined.set(new Uint8Array(encrypted), iv.length);
27301
+ return bufferToBase64(combined);
26807
27302
  }
26808
- if (namespace.type === "packed") {
26809
- const pkg = registry.packages[namespace.packageId];
26810
- if (pkg) {
26811
- const loader2 = pkg.hooks[shortName];
26812
- if (loader2) {
26813
- return loader2;
26814
- }
26815
- }
26816
- return null;
27303
+ /**
27304
+ * Decrypt a string value
27305
+ */
27306
+ static async decrypt(encryptedText, key) {
27307
+ const combined = base64ToBuffer2(encryptedText);
27308
+ const iv = combined.slice(0, 12);
27309
+ const encrypted = combined.slice(12);
27310
+ const cryptoKey = await crypto.subtle.importKey(
27311
+ "raw",
27312
+ hexToBuffer(key),
27313
+ { name: "AES-GCM" },
27314
+ false,
27315
+ ["decrypt"]
27316
+ );
27317
+ const decrypted = await crypto.subtle.decrypt(
27318
+ {
27319
+ name: "AES-GCM",
27320
+ iv
27321
+ },
27322
+ cryptoKey,
27323
+ encrypted
27324
+ );
27325
+ const decoder = new TextDecoder();
27326
+ return decoder.decode(decrypted);
26817
27327
  }
26818
- const loader = registry.global.hooks[shortName];
26819
- return loader || null;
26820
- }
26821
- function getVisibleToolNames(registry, namespace) {
26822
- if (namespace.type === "packed") {
26823
- const pkg = registry.packages[namespace.packageId];
26824
- return pkg ? Object.keys(pkg.tools) : [];
27328
+ };
27329
+ function hexToBuffer(hex) {
27330
+ const bytes = new Uint8Array(hex.length / 2);
27331
+ for (let i = 0; i < hex.length; i += 2) {
27332
+ bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
26825
27333
  }
26826
- return Object.keys(registry.global.tools);
27334
+ return bytes;
26827
27335
  }
26828
- function getVisibleAgentNames(registry, namespace) {
26829
- if (namespace.type === "packed") {
26830
- const pkg = registry.packages[namespace.packageId];
26831
- const ownAgents = pkg ? Object.keys(pkg.agents) : [];
26832
- const otherEntryPoints = Object.entries(registry.packages).filter(([id]) => id !== namespace.packageId).flatMap(
26833
- ([pkgId, pkg2]) => pkg2.entryAgents.map((name) => qualifyName(pkgId, name))
26834
- );
26835
- return [...ownAgents, ...otherEntryPoints];
27336
+ function bufferToBase64(buffer) {
27337
+ let binary = "";
27338
+ for (let i = 0; i < buffer.byteLength; i++) {
27339
+ binary += String.fromCharCode(buffer[i]);
26836
27340
  }
26837
- const globalAgents = Object.keys(registry.global.agents);
26838
- const entryPoints = Object.values(registry.packages).flatMap((pkg) => pkg.entryAgents);
26839
- return [.../* @__PURE__ */ new Set([...globalAgents, ...entryPoints])];
27341
+ return btoa(binary);
26840
27342
  }
26841
- function getVisiblePromptNames(registry, namespace) {
26842
- if (namespace.type === "packed") {
26843
- const pkg = registry.packages[namespace.packageId];
26844
- return pkg ? Object.keys(pkg.prompts) : [];
27343
+ function base64ToBuffer2(base64) {
27344
+ const binary = atob(base64);
27345
+ const bytes = new Uint8Array(binary.length);
27346
+ for (let i = 0; i < binary.length; i++) {
27347
+ bytes[i] = binary.charCodeAt(i);
26845
27348
  }
26846
- return Object.keys(registry.global.prompts);
27349
+ return bytes;
26847
27350
  }
26848
- function getVisibleModelNames(registry, namespace) {
26849
- if (namespace.type === "packed") {
26850
- const pkg = registry.packages[namespace.packageId];
26851
- const ownModels = pkg ? Object.keys(pkg.models) : [];
26852
- const globalModels = Object.keys(registry.global.models);
26853
- return [.../* @__PURE__ */ new Set([...ownModels, ...globalModels])];
26854
- }
26855
- return Object.keys(registry.global.models);
27351
+ async function encryptEnvs(env, encryptionKey) {
27352
+ const plaintext = JSON.stringify(env);
27353
+ return CryptoUtil.encrypt(plaintext, encryptionKey);
26856
27354
  }
26857
- function createNamespaceContext(agentDef) {
26858
- if (agentDef?.__package) {
26859
- return { type: "packed", packageId: agentDef.__package.packageId };
27355
+ async function decryptEnvs(encrypted, encryptionKey) {
27356
+ const plaintext = await CryptoUtil.decrypt(encrypted, encryptionKey);
27357
+ const parsed = JSON.parse(plaintext);
27358
+ if (!parsed || typeof parsed !== "object") {
27359
+ return {};
26860
27360
  }
26861
- return { type: "global" };
26862
- }
26863
- function isQualifiedName(name) {
26864
- if (name.startsWith("@")) {
26865
- const firstSlash = name.indexOf("/");
26866
- if (firstSlash === -1) return false;
26867
- return name.indexOf("/", firstSlash + 1) !== -1;
27361
+ const result = {};
27362
+ for (const [key, value] of Object.entries(parsed)) {
27363
+ if (value === void 0 || value === null) continue;
27364
+ result[key] = String(value);
26868
27365
  }
26869
- return name.includes("/");
27366
+ return result;
26870
27367
  }
26871
27368
 
26872
27369
  // src/durable-objects/DurableAgentBuilder.ts
27370
+ init_resolver();
26873
27371
  init_types();
26874
27372
 
26875
27373
  // src/skills/frontmatter.ts
@@ -26961,6 +27459,7 @@ function validateSkillFiles(files) {
26961
27459
 
26962
27460
  // src/durable-objects/DurableAgentBuilder.ts
26963
27461
  init_scope();
27462
+ init_ParentHookResolver();
26964
27463
  var ENV_TYPES_PROPERTY = "__agentbuilder_env_types";
26965
27464
  function parseStoredPermissions(value) {
26966
27465
  if (typeof value !== "string" || !value.trim()) return null;
@@ -27642,16 +28141,29 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
27642
28141
  } catch {
27643
28142
  return;
27644
28143
  }
27645
- const hookIds = Array.isArray(agentDef?.hooks) ? agentDef.hooks : [];
27646
- if (hookIds.length === 0) {
27647
- return;
27648
- }
27649
- let hooksRegistry;
27650
- try {
27651
- hooksRegistry = this.hooks();
27652
- } catch {
27653
- return;
27654
- }
28144
+ const packageId = agentDef?.__package?.packageId;
28145
+ const rawPromptName = agentDef?.sideA?.prompt;
28146
+ const promptName = rawPromptName && packageId && !isQualifiedName(rawPromptName) ? `${packageId}/${rawPromptName}` : rawPromptName;
28147
+ const promptDef = promptName ? await this.loadPrompt(promptName) : void 0;
28148
+ const bindings = await resolveHooksForPrompt(
28149
+ {
28150
+ host: this,
28151
+ agentName: thread.agent_name,
28152
+ agent: agentDef,
28153
+ promptName,
28154
+ prompt: promptDef,
28155
+ isOptionalRelationshipEnabled: async (envName) => {
28156
+ const value = await this.resolveThreadEnv({
28157
+ threadId: thread.id,
28158
+ property: envName,
28159
+ promptName: promptName ?? agentDef.name ?? thread.agent_name
28160
+ });
28161
+ return ["true", "1", "yes"].includes((value ?? "").trim().toLowerCase());
28162
+ }
28163
+ },
28164
+ "after_thread_created"
28165
+ );
28166
+ if (bindings.length === 0) return;
27655
28167
  const durableId = this.env.AGENT_BUILDER_THREAD.idFromName(thread.id);
27656
28168
  const threadStub = this.env.AGENT_BUILDER_THREAD.get(durableId);
27657
28169
  const { ThreadStateImpl: ThreadStateImpl2 } = await Promise.resolve().then(() => (init_ThreadStateImpl(), ThreadStateImpl_exports));
@@ -27666,16 +28178,14 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
27666
28178
  terminated: thread.terminated,
27667
28179
  created_at: thread.created_at
27668
28180
  });
27669
- for (const hookId of hookIds) {
27670
- const hookLoader = hooksRegistry[hookId];
27671
- if (!hookLoader) continue;
28181
+ for (const binding of bindings) {
27672
28182
  try {
27673
- const hookDef = await hookLoader();
27674
- if (hookDef?.hook === "after_thread_created") {
27675
- await hookDef.execute(threadState);
27676
- }
28183
+ await binding.execute(threadState, binding.context);
27677
28184
  } catch (error) {
27678
- console.error(`[Hooks] \u2717 Error running after_thread_created hook '${hookId}':`, error);
28185
+ console.error(
28186
+ `[Hooks] \u2717 Error running after_thread_created hook '${binding.id}':`,
28187
+ error
28188
+ );
27679
28189
  }
27680
28190
  }
27681
28191
  }
@@ -28887,6 +29397,15 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
28887
29397
  * Load a prompt definition by name.
28888
29398
  */
28889
29399
  async loadPrompt(name) {
29400
+ if (isQualifiedName(name)) {
29401
+ const [packageId, promptName] = parseQualifiedName(name);
29402
+ const pkg = packageId ? this.registry()?.packages?.[packageId] : void 0;
29403
+ const loader2 = pkg?.prompts?.[promptName];
29404
+ if (!loader2) {
29405
+ throw new Error(`Prompt not found: ${name}`);
29406
+ }
29407
+ return await loader2();
29408
+ }
28890
29409
  const registry = this.prompts();
28891
29410
  const loader = registry[name];
28892
29411
  if (!loader) {
@@ -30126,6 +30645,17 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
30126
30645
  }
30127
30646
  return { status: row.status };
30128
30647
  }
30648
+ /** Deny a pending device login without creating a user or API key. */
30649
+ async denyDeviceLogin(codeHash) {
30650
+ await this.ensureMigrated();
30651
+ await this.sweepDeviceLogins();
30652
+ const cursor = await this.ctx.storage.sql.exec(
30653
+ `UPDATE device_logins SET status = 'denied', user_id = NULL, token = NULL
30654
+ WHERE code_hash = ? AND status = 'pending'`,
30655
+ codeHash
30656
+ );
30657
+ return cursor.rowsWritten > 0;
30658
+ }
30129
30659
  /** Approve a pending device login: mint a personal API key for the user and
30130
30660
  * park its plaintext for the single claim. Returns false when the code is
30131
30661
  * unknown, expired, or not pending. */
@@ -30176,6 +30706,7 @@ ${result ?? error ?? "No result content."}${attachmentSummary}`;
30176
30706
  init_StreamManager();
30177
30707
  init_LLMRequest();
30178
30708
  init_ThreadStateImpl();
30709
+ init_resolver();
30179
30710
 
30180
30711
  // src/durable-objects/logDetailStream.ts
30181
30712
  var LOG_DETAIL_HEAVY_FIELDS = [
@@ -30849,6 +31380,7 @@ var DurableThread = class _DurableThread extends DurableObject {
30849
31380
  type: agentDef.type,
30850
31381
  created_at: Date.now(),
30851
31382
  max_session_turns: agentDef.maxSessionTurns,
31383
+ _package: agentDef.__package,
30852
31384
  side_a_label: agentDef.sideA?.label,
30853
31385
  side_a_agent_prompt: qualifyPromptName(agentDef.sideA?.prompt),
30854
31386
  side_a_stop_on_response: agentDef.sideA?.stopOnResponse ?? true,
@@ -36083,6 +36615,8 @@ Its execution was lost (the executor restarted or hung) and automatic recovery w
36083
36615
  type: agentDef.type,
36084
36616
  created_at: Date.now(),
36085
36617
  max_session_turns: agentDef.maxSessionTurns,
36618
+ hooks: agentDef.hooks ?? [],
36619
+ _package: agentDef.__package,
36086
36620
  side_a_label: agentDef.sideA?.label,
36087
36621
  side_a_agent_prompt: qualifyPromptName(agentDef.sideA?.prompt),
36088
36622
  side_a_stop_on_response: agentDef.sideA?.stopOnResponse ?? true,
@@ -36308,6 +36842,8 @@ Its execution was lost (the executor restarted or hung) and automatic recovery w
36308
36842
  type: agentDef.type,
36309
36843
  created_at: Date.now(),
36310
36844
  max_session_turns: agentDef.maxSessionTurns,
36845
+ hooks: agentDef.hooks ?? [],
36846
+ _package: agentDef.__package,
36311
36847
  side_a_label: agentDef.sideA?.label,
36312
36848
  side_a_agent_prompt: qualifyPromptName(agentDef.sideA?.prompt),
36313
36849
  side_a_stop_on_response: agentDef.sideA?.stopOnResponse ?? true,
@@ -36464,6 +37000,8 @@ Its execution was lost (the executor restarted or hung) and automatic recovery w
36464
37000
  type: agentDef.type,
36465
37001
  created_at: Date.now(),
36466
37002
  max_session_turns: agentDef.maxSessionTurns,
37003
+ hooks: agentDef.hooks ?? [],
37004
+ _package: agentDef.__package,
36467
37005
  side_a_label: agentDef.sideA?.label,
36468
37006
  side_a_agent_prompt: qualifyPromptName(agentDef.sideA?.prompt),
36469
37007
  side_a_stop_on_response: agentDef.sideA?.stopOnResponse ?? true,
@@ -38421,6 +38959,9 @@ init_context();
38421
38959
  init_ProviderRegistry();
38422
38960
  init_types2();
38423
38961
 
38962
+ // src/packing/index.ts
38963
+ init_resolver();
38964
+
38424
38965
  export { CLIENT_STREAM_CHUNK_BYTES, CodeExecutionBridge, DurableAgentBuilder, DurableThread, DurableUserHub, FlowStateSdk, NamespaceResolutionError, PackageDiscoveryService, ProviderRegistry, ThreadWatchdog, agentbuilder, applyRuntimeCors, assistantMessageText, authenticate, buildImageDescription, builder, callClient, callClientStream, canAccessThread, cat, createNamespaceContext, createThreadEndpointHandler, decodeStreamChunk, defineController2 as defineController, discoverPackages, emitThreadEvent, encodeStreamChunk, endpointCallerFromAuth, enhanceFlowState, exists, find, forceTurn, generateAgentFile, generateImageDescription, generateModelFile, generatePromptFile, getFileStats, getMessages, getMessagesToSummarize, getShortName, getThumbnail, getUnsummarizedImageAttachments, getVisibleAgentNames, getVisibleModelNames, getVisiblePromptNames, getVisibleToolNames, grep, hasImageAttachments, hasJsonArrayEntries, head, injectMessage, isAdminOnlyApiRoute, isHostedInstance, isPublicApiRoute, isQualifiedName, isSameOriginBrowserRequest, isTrustedLocalDevelopmentRequest, isVisibleTerminalAssistantMessage, linkFile, messageTimestampSeconds, mkdir, move, optimizeImageContext, parseQualifiedName, qualifyName, queueTool, readFile, readdir, reloadHistory, rename, replaceImagesWithDescriptions, requireAdmin, requireAuth, resolveAgent, resolveHook, resolveModel, resolvePrompt, resolveTool, rmdir, runtimeCorsHeaders, runtimePreflightResponse, stat, supportsClientForwarding, tail, unlink, updateThread, writeFile, writeImage };
38425
38966
  //# sourceMappingURL=index.js.map
38426
38967
  //# sourceMappingURL=index.js.map