@mj-biz-apps/marketing-server 0.0.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +183 -0
- package/dist/agents/BaseMarketingAgent.d.ts +120 -0
- package/dist/agents/BaseMarketingAgent.d.ts.map +1 -0
- package/dist/agents/BaseMarketingAgent.js +323 -0
- package/dist/agents/BaseMarketingAgent.js.map +1 -0
- package/dist/agents/MarketingExperimentationAgent.d.ts +123 -0
- package/dist/agents/MarketingExperimentationAgent.d.ts.map +1 -0
- package/dist/agents/MarketingExperimentationAgent.js +371 -0
- package/dist/agents/MarketingExperimentationAgent.js.map +1 -0
- package/dist/agents/MarketingOperationsAgent.d.ts +24 -0
- package/dist/agents/MarketingOperationsAgent.d.ts.map +1 -0
- package/dist/agents/MarketingOperationsAgent.js +36 -0
- package/dist/agents/MarketingOperationsAgent.js.map +1 -0
- package/dist/agents/MarketingPodcastIngestionAgent.d.ts +21 -0
- package/dist/agents/MarketingPodcastIngestionAgent.d.ts.map +1 -0
- package/dist/agents/MarketingPodcastIngestionAgent.js +33 -0
- package/dist/agents/MarketingPodcastIngestionAgent.js.map +1 -0
- package/dist/agents/MarketingStrategyOnboardingAgent.d.ts +206 -0
- package/dist/agents/MarketingStrategyOnboardingAgent.d.ts.map +1 -0
- package/dist/agents/MarketingStrategyOnboardingAgent.js +1264 -0
- package/dist/agents/MarketingStrategyOnboardingAgent.js.map +1 -0
- package/dist/agents/index.d.ts +14 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +25 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +6 -0
- package/dist/config.js.map +1 -0
- package/dist/generated/class-registrations-manifest.d.ts +7 -0
- package/dist/generated/class-registrations-manifest.d.ts.map +1 -0
- package/dist/generated/class-registrations-manifest.js +7 -0
- package/dist/generated/class-registrations-manifest.js.map +1 -0
- package/dist/generated/generated.d.ts +7 -0
- package/dist/generated/generated.d.ts.map +1 -0
- package/dist/generated/generated.js +7 -0
- package/dist/generated/generated.js.map +1 -0
- package/dist/generated/graphql-schemas/__mj_BizAppsMarketing.d.ts +3522 -0
- package/dist/generated/graphql-schemas/__mj_BizAppsMarketing.d.ts.map +1 -0
- package/dist/generated/graphql-schemas/__mj_BizAppsMarketing.js +18854 -0
- package/dist/generated/graphql-schemas/__mj_BizAppsMarketing.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +107 -0
- package/dist/index.js.map +1 -0
- package/dist/programs/ContentPostProgramDriver.d.ts +44 -0
- package/dist/programs/ContentPostProgramDriver.d.ts.map +1 -0
- package/dist/programs/ContentPostProgramDriver.js +185 -0
- package/dist/programs/ContentPostProgramDriver.js.map +1 -0
- package/dist/programs/EmailProgramDriver.d.ts +56 -0
- package/dist/programs/EmailProgramDriver.d.ts.map +1 -0
- package/dist/programs/EmailProgramDriver.js +224 -0
- package/dist/programs/EmailProgramDriver.js.map +1 -0
- package/dist/programs/google/GoogleAdsClient.d.ts +93 -0
- package/dist/programs/google/GoogleAdsClient.d.ts.map +1 -0
- package/dist/programs/google/GoogleAdsClient.js +279 -0
- package/dist/programs/google/GoogleAdsClient.js.map +1 -0
- package/dist/programs/google/GoogleAdsProgramDriver.d.ts +56 -0
- package/dist/programs/google/GoogleAdsProgramDriver.d.ts.map +1 -0
- package/dist/programs/google/GoogleAdsProgramDriver.js +357 -0
- package/dist/programs/google/GoogleAdsProgramDriver.js.map +1 -0
- package/dist/programs/google/googleAdsExecutionContext.d.ts +47 -0
- package/dist/programs/google/googleAdsExecutionContext.d.ts.map +1 -0
- package/dist/programs/google/googleAdsExecutionContext.js +128 -0
- package/dist/programs/google/googleAdsExecutionContext.js.map +1 -0
- package/dist/programs/google/googleBrandAssets.d.ts +27 -0
- package/dist/programs/google/googleBrandAssets.d.ts.map +1 -0
- package/dist/programs/google/googleBrandAssets.js +81 -0
- package/dist/programs/google/googleBrandAssets.js.map +1 -0
- package/dist/programs/index.d.ts +18 -0
- package/dist/programs/index.d.ts.map +1 -0
- package/dist/programs/index.js +27 -0
- package/dist/programs/index.js.map +1 -0
- package/dist/programs/linkedin/LinkedInAdsClient.d.ts +145 -0
- package/dist/programs/linkedin/LinkedInAdsClient.d.ts.map +1 -0
- package/dist/programs/linkedin/LinkedInAdsClient.js +408 -0
- package/dist/programs/linkedin/LinkedInAdsClient.js.map +1 -0
- package/dist/programs/linkedin/LinkedInAdsProgramDriver.d.ts +94 -0
- package/dist/programs/linkedin/LinkedInAdsProgramDriver.d.ts.map +1 -0
- package/dist/programs/linkedin/LinkedInAdsProgramDriver.js +449 -0
- package/dist/programs/linkedin/LinkedInAdsProgramDriver.js.map +1 -0
- package/dist/programs/linkedin/linkedInExecutionContext.d.ts +42 -0
- package/dist/programs/linkedin/linkedInExecutionContext.d.ts.map +1 -0
- package/dist/programs/linkedin/linkedInExecutionContext.js +97 -0
- package/dist/programs/linkedin/linkedInExecutionContext.js.map +1 -0
- package/package.json +46 -7
- package/index.js +0 -1
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import type { AgentConfiguration, AIPromptParams, ExecuteAgentParams, BaseAgentNextStep, MJAIAgentRunEntityExtended, MJAIAgentRunStepEntityExtended } from '@memberjunction/ai-core-plus';
|
|
2
|
+
import { BaseMarketingAgent } from './BaseMarketingAgent.js';
|
|
3
|
+
/**
|
|
4
|
+
* Marketing Programs Agent — driver class.
|
|
5
|
+
*
|
|
6
|
+
* The `MJ: AI Agents` metadata row has declared `DriverClass = MarketingExperimentationAgent`
|
|
7
|
+
* since the agent was seeded, but no such class existed, so MJ's ClassFactory silently fell back
|
|
8
|
+
* to plain `BaseAgent` and none of the doctrine below was enforced. (Exactly what had happened to
|
|
9
|
+
* MarketingStrategyOnboardingAgent before its driver class was written.)
|
|
10
|
+
*
|
|
11
|
+
* PRD §4 is binding on this agent, and the division of labour follows from it:
|
|
12
|
+
*
|
|
13
|
+
* * "Code owns numbers and dates" — the agent NEVER computes a metric, a threshold comparison,
|
|
14
|
+
* or a decision. `findingSynthesis` composes the factual finding from measured values before
|
|
15
|
+
* the agent is consulted.
|
|
16
|
+
* * "No invented evidence" — the agent's only contribution to a Learning is the MECHANISM, the
|
|
17
|
+
* causal reading that code cannot derive. It passes through `enrichFinding`, which rejects any
|
|
18
|
+
* interpretation citing a number that is not among the measured facts, or asserting an outcome
|
|
19
|
+
* that contradicts the recorded decision.
|
|
20
|
+
* * "Flow-critical outcomes run in post-hooks, never as optional LLM tool calls" — the learning
|
|
21
|
+
* write happens in `validateSuccessNextStep` below. It is not a tool the model may decline to
|
|
22
|
+
* call, because a decision that produces no Learning is the failure mode this whole framework
|
|
23
|
+
* exists to prevent.
|
|
24
|
+
* * "The prompt narrates published state" — the agent may not claim a program launched or
|
|
25
|
+
* decided. Those transitions belong to the lifecycle service, which the agent does not call.
|
|
26
|
+
*/
|
|
27
|
+
export declare class MarketingExperimentationAgent extends BaseMarketingAgent {
|
|
28
|
+
/**
|
|
29
|
+
* Payload key the prompt writes its causal reading into.
|
|
30
|
+
*
|
|
31
|
+
* Deliberately named for what it is. The model is asked for a mechanism WITHOUT numbers — the
|
|
32
|
+
* numbers are already in the factual sentence this gets appended to, and every number the model
|
|
33
|
+
* adds is one more thing the guard has to reject.
|
|
34
|
+
*/
|
|
35
|
+
private static readonly INTERPRETATION_KEY;
|
|
36
|
+
/** Payload key naming which decided program the interpretation is about. */
|
|
37
|
+
private static readonly PROGRAM_KEY;
|
|
38
|
+
/**
|
|
39
|
+
* Injects the program knowledge base before every prompt turn.
|
|
40
|
+
*
|
|
41
|
+
* This is what makes the agent propose FROM evidence rather than from the strategy document
|
|
42
|
+
* plus its own priors. It runs on every turn, deterministically, in code — not as a tool the
|
|
43
|
+
* model may choose to call, because an agent that can decline to look at prior results will
|
|
44
|
+
* eventually propose something that was already killed.
|
|
45
|
+
*
|
|
46
|
+
* Exposed to the template as `{{ programKnowledge }}`. A load failure is logged and the turn
|
|
47
|
+
* proceeds WITHOUT the block rather than aborting: losing the history degrades proposal
|
|
48
|
+
* quality, while failing the run loses the turn entirely. The block is self-describing, so its
|
|
49
|
+
* absence cannot be mistaken by the model for "there is no history".
|
|
50
|
+
*/
|
|
51
|
+
protected preparePromptParams<P>(config: AgentConfiguration, payload: P, params: ExecuteAgentParams): Promise<AIPromptParams>;
|
|
52
|
+
/**
|
|
53
|
+
* The text findings are ranked against, drawn from the conversation.
|
|
54
|
+
*
|
|
55
|
+
* The obvious candidate — the draft hypothesis — does not exist yet: this runs BEFORE the model
|
|
56
|
+
* writes anything. What does exist is the user's request, which is what the turn is about, so it
|
|
57
|
+
* is the honest relevance signal available at this point.
|
|
58
|
+
*
|
|
59
|
+
* Returns null for a short or generic request ("review the programs", "what next?"). Ranking
|
|
60
|
+
* against those would narrow the corpus on noise, and a narrowed corpus is strictly worse than
|
|
61
|
+
* the full one when the query carries no topic — the model would lose evidence and be told the
|
|
62
|
+
* remainder was "most relevant".
|
|
63
|
+
*/
|
|
64
|
+
private retrievalQuery;
|
|
65
|
+
/**
|
|
66
|
+
* Post-hook: fold the agent's mechanism into the Learning the decision already recorded.
|
|
67
|
+
*
|
|
68
|
+
* Runs after a successful step, so it sees the payload the model produced. Everything it needs
|
|
69
|
+
* beyond that comes from the database, never from the model: the program's own numbers, and
|
|
70
|
+
* the Learning row the writeback wrote.
|
|
71
|
+
*
|
|
72
|
+
* Failures here are logged and swallowed. A missing mechanism leaves a Learning that is still
|
|
73
|
+
* true and still cites its numbers; aborting the agent run over it would trade a complete
|
|
74
|
+
* record for no record.
|
|
75
|
+
*/
|
|
76
|
+
protected validateSuccessNextStep<P>(params: ExecuteAgentParams, nextStep: BaseAgentNextStep<P>, currentPayload: P, agentRun: MJAIAgentRunEntityExtended, currentStep: MJAIAgentRunStepEntityExtended): Promise<BaseAgentNextStep<P>>;
|
|
77
|
+
/** A turn that ends by asking the user something can still have proposed — same stamp. */
|
|
78
|
+
protected validateChatNextStep<P>(params: ExecuteAgentParams, nextStep: BaseAgentNextStep<P>, currentPayload: P, agentRun: MJAIAgentRunEntityExtended, currentStep: MJAIAgentRunStepEntityExtended): Promise<BaseAgentNextStep<P>>;
|
|
79
|
+
/**
|
|
80
|
+
* Decides, in code, whether this run may SAVE a proposal or only DRAFT one.
|
|
81
|
+
*
|
|
82
|
+
* Inside the in-app Assistant a person is reading the proposal as it is written, so the
|
|
83
|
+
* Program row is theirs to create: the run drafts (`Propose Program` with `DraftOnly=true`)
|
|
84
|
+
* and the proposal card's Approve click commits. Everywhere else — the hourly agent, sprint
|
|
85
|
+
* end, a scheduled job — nobody is watching, and a draft nobody can see would simply be lost,
|
|
86
|
+
* so those runs commit directly and queue for approval as before.
|
|
87
|
+
*
|
|
88
|
+
* The Assistant is recognised by the app context it sends (the same signal that makes the
|
|
89
|
+
* brand picker authoritative). The template reads `proposalMode`; it does not decide it.
|
|
90
|
+
*/
|
|
91
|
+
protected initializeStartingPayload<P = unknown>(params: ExecuteAgentParams<unknown, P>): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Stamps what THIS run proposed onto the payload, as `proposals`.
|
|
94
|
+
*
|
|
95
|
+
* The payload is what the conversation renders as the run's artifact, and the proposal card
|
|
96
|
+
* is drawn from this list. It is built from the run's own recorded `Propose Program` action
|
|
97
|
+
* results — never from the model's account of what it did ("the prompt narrates published
|
|
98
|
+
* state"):
|
|
99
|
+
* * DRAFTED → the full validated draft rides along, because no row exists to load. The card
|
|
100
|
+
* renders it, and re-submits exactly these inputs when the user approves.
|
|
101
|
+
* * SUCCESS → a committed program; ids only, and the card loads the row live.
|
|
102
|
+
* A failed or blocked call produced no proposal and is skipped.
|
|
103
|
+
*/
|
|
104
|
+
private attachProposals;
|
|
105
|
+
/** One recorded `Propose Program` result → a proposal reference, or null when it produced none. */
|
|
106
|
+
private proposalFromStep;
|
|
107
|
+
/**
|
|
108
|
+
* Applies the model's mechanism to the most recent Learning for the named program.
|
|
109
|
+
*
|
|
110
|
+
* No-ops silently when the payload carries no interpretation — the agent has other jobs
|
|
111
|
+
* (proposing), and only the decision-interpretation turn produces one.
|
|
112
|
+
*/
|
|
113
|
+
private applyLearningInterpretation;
|
|
114
|
+
/**
|
|
115
|
+
* `Program.Decision` is title-case ('Keep'); the writeback rules are upper-case ('KEEP').
|
|
116
|
+
* The two columns genuinely disagree on casing, so the mapping is explicit rather than a
|
|
117
|
+
* `toUpperCase()` that would quietly produce an invalid value for anything unexpected.
|
|
118
|
+
*/
|
|
119
|
+
private toDecisionOutcome;
|
|
120
|
+
}
|
|
121
|
+
/** Anti-tree-shaking loader — the @RegisterClass above is a side effect. */
|
|
122
|
+
export declare function LoadMarketingExperimentationAgent(): void;
|
|
123
|
+
//# sourceMappingURL=MarketingExperimentationAgent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarketingExperimentationAgent.d.ts","sourceRoot":"","sources":["../../src/agents/MarketingExperimentationAgent.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAa1L,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAmC7D;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,qBACa,6BAA8B,SAAQ,kBAAkB;IACjE;;;;;;OAMG;IACH,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAA4B;IAEtE,4EAA4E;IAC5E,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAA0B;IAE7D;;;;;;;;;;;;OAYG;cACsB,mBAAmB,CAAC,CAAC,EAC1C,MAAM,EAAE,kBAAkB,EAC1B,OAAO,EAAE,CAAC,EACV,MAAM,EAAE,kBAAkB,GAC3B,OAAO,CAAC,cAAc,CAAC;IA6B1B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,cAAc;IAkBtB;;;;;;;;;;OAUG;cACsB,uBAAuB,CAAC,CAAC,EAC9C,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC9B,cAAc,EAAE,CAAC,EACjB,QAAQ,EAAE,0BAA0B,EACpC,WAAW,EAAE,8BAA8B,GAC5C,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAahC,0FAA0F;cACjE,oBAAoB,CAAC,CAAC,EAC3C,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC9B,cAAc,EAAE,CAAC,EACjB,QAAQ,EAAE,0BAA0B,EACpC,WAAW,EAAE,8BAA8B,GAC5C,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;IAMhC;;;;;;;;;;;OAWG;cACsB,yBAAyB,CAAC,CAAC,GAAG,OAAO,EAAE,MAAM,EAAE,kBAAkB,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtH;;;;;;;;;;;OAWG;YACW,eAAe;IAkC7B,mGAAmG;IACnG,OAAO,CAAC,gBAAgB;IA0CxB;;;;;OAKG;YACW,2BAA2B;IA0FzC;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;CAc5B;AAED,4EAA4E;AAC5E,wBAAgB,iCAAiC,IAAI,IAAI,CAAG"}
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var MarketingExperimentationAgent_1;
|
|
8
|
+
import { EscapeSQLString, RegisterClass } from '@memberjunction/global';
|
|
9
|
+
import { BaseAgent } from '@memberjunction/ai-agents';
|
|
10
|
+
import { LogStatus, LogError, Metadata, RunView } from '@memberjunction/core';
|
|
11
|
+
import { enrichFinding, loadProgramKnowledge, renderKnowledgeBase, toMarketingEntityName, } from '@mj-biz-apps/marketing-core';
|
|
12
|
+
import { BaseMarketingAgent } from './BaseMarketingAgent.js';
|
|
13
|
+
/** Below this, a request is too short to rank a corpus against. */
|
|
14
|
+
const MIN_RETRIEVAL_QUERY_CHARS = 25;
|
|
15
|
+
/**
|
|
16
|
+
* Process vocabulary that says nothing about SUBJECT. "Review the programs and propose one"
|
|
17
|
+
* is a valid instruction and a useless retrieval query — stripping these leaves nothing, which is
|
|
18
|
+
* the signal to fall back to the full corpus.
|
|
19
|
+
*/
|
|
20
|
+
const GENERIC_REQUEST_WORDS = /\b(review|propose|suggest|new|next|one|an?|the|and|or|for|to|of|please|what|should|we|i|you|program|programs|please|now|then|also|with|from|this|that|it|be|do|make|create|give|me|us|any|some|based|on|using|cite|codes?|numbers?)\b/g;
|
|
21
|
+
/**
|
|
22
|
+
* Marketing Programs Agent — driver class.
|
|
23
|
+
*
|
|
24
|
+
* The `MJ: AI Agents` metadata row has declared `DriverClass = MarketingExperimentationAgent`
|
|
25
|
+
* since the agent was seeded, but no such class existed, so MJ's ClassFactory silently fell back
|
|
26
|
+
* to plain `BaseAgent` and none of the doctrine below was enforced. (Exactly what had happened to
|
|
27
|
+
* MarketingStrategyOnboardingAgent before its driver class was written.)
|
|
28
|
+
*
|
|
29
|
+
* PRD §4 is binding on this agent, and the division of labour follows from it:
|
|
30
|
+
*
|
|
31
|
+
* * "Code owns numbers and dates" — the agent NEVER computes a metric, a threshold comparison,
|
|
32
|
+
* or a decision. `findingSynthesis` composes the factual finding from measured values before
|
|
33
|
+
* the agent is consulted.
|
|
34
|
+
* * "No invented evidence" — the agent's only contribution to a Learning is the MECHANISM, the
|
|
35
|
+
* causal reading that code cannot derive. It passes through `enrichFinding`, which rejects any
|
|
36
|
+
* interpretation citing a number that is not among the measured facts, or asserting an outcome
|
|
37
|
+
* that contradicts the recorded decision.
|
|
38
|
+
* * "Flow-critical outcomes run in post-hooks, never as optional LLM tool calls" — the learning
|
|
39
|
+
* write happens in `validateSuccessNextStep` below. It is not a tool the model may decline to
|
|
40
|
+
* call, because a decision that produces no Learning is the failure mode this whole framework
|
|
41
|
+
* exists to prevent.
|
|
42
|
+
* * "The prompt narrates published state" — the agent may not claim a program launched or
|
|
43
|
+
* decided. Those transitions belong to the lifecycle service, which the agent does not call.
|
|
44
|
+
*/
|
|
45
|
+
let MarketingExperimentationAgent = class MarketingExperimentationAgent extends BaseMarketingAgent {
|
|
46
|
+
static { MarketingExperimentationAgent_1 = this; }
|
|
47
|
+
/**
|
|
48
|
+
* Payload key the prompt writes its causal reading into.
|
|
49
|
+
*
|
|
50
|
+
* Deliberately named for what it is. The model is asked for a mechanism WITHOUT numbers — the
|
|
51
|
+
* numbers are already in the factual sentence this gets appended to, and every number the model
|
|
52
|
+
* adds is one more thing the guard has to reject.
|
|
53
|
+
*/
|
|
54
|
+
static { this.INTERPRETATION_KEY = 'learningInterpretation'; }
|
|
55
|
+
/** Payload key naming which decided program the interpretation is about. */
|
|
56
|
+
static { this.PROGRAM_KEY = 'interpretedProgramId'; }
|
|
57
|
+
/**
|
|
58
|
+
* Injects the program knowledge base before every prompt turn.
|
|
59
|
+
*
|
|
60
|
+
* This is what makes the agent propose FROM evidence rather than from the strategy document
|
|
61
|
+
* plus its own priors. It runs on every turn, deterministically, in code — not as a tool the
|
|
62
|
+
* model may choose to call, because an agent that can decline to look at prior results will
|
|
63
|
+
* eventually propose something that was already killed.
|
|
64
|
+
*
|
|
65
|
+
* Exposed to the template as `{{ programKnowledge }}`. A load failure is logged and the turn
|
|
66
|
+
* proceeds WITHOUT the block rather than aborting: losing the history degrades proposal
|
|
67
|
+
* quality, while failing the run loses the turn entirely. The block is self-describing, so its
|
|
68
|
+
* absence cannot be mistaken by the model for "there is no history".
|
|
69
|
+
*/
|
|
70
|
+
async preparePromptParams(config, payload, params) {
|
|
71
|
+
const result = await super.preparePromptParams(config, payload, params);
|
|
72
|
+
const bag = (payload ?? {});
|
|
73
|
+
const brandId = typeof bag['brandId'] === 'string' ? bag['brandId'] : null;
|
|
74
|
+
if (!brandId || !result.data)
|
|
75
|
+
return result;
|
|
76
|
+
try {
|
|
77
|
+
// Rank the corpus against what is actually being asked, when there is something to rank
|
|
78
|
+
// against. The draft hypothesis does not exist yet at injection time — the model has not
|
|
79
|
+
// written one — so the user's request is the best available signal for relevance, and it
|
|
80
|
+
// is what the whole turn is about.
|
|
81
|
+
const relevantTo = this.retrievalQuery(params);
|
|
82
|
+
const kb = await loadProgramKnowledge({
|
|
83
|
+
brandId,
|
|
84
|
+
contextUser: params.contextUser,
|
|
85
|
+
...(relevantTo ? { relevantTo } : {}),
|
|
86
|
+
});
|
|
87
|
+
result.data['programKnowledge'] = renderKnowledgeBase(kb);
|
|
88
|
+
LogStatus(`MarketingExperimentationAgent: injected ${kb.learnings.length} finding(s) and `
|
|
89
|
+
+ `${kb.sprints.length} sprint(s) of history (${kb.excludedStrategyFacts} strategy fact(s) excluded)`
|
|
90
|
+
+ `${kb.rankedSemantically ? ` — ranked semantically against "${(relevantTo ?? '').slice(0, 60)}…"` : ' — date order'}.`);
|
|
91
|
+
}
|
|
92
|
+
catch (e) {
|
|
93
|
+
LogError('MarketingExperimentationAgent: knowledge base load failed, proceeding without it — '
|
|
94
|
+
+ (e instanceof Error ? e.message : String(e)));
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The text findings are ranked against, drawn from the conversation.
|
|
100
|
+
*
|
|
101
|
+
* The obvious candidate — the draft hypothesis — does not exist yet: this runs BEFORE the model
|
|
102
|
+
* writes anything. What does exist is the user's request, which is what the turn is about, so it
|
|
103
|
+
* is the honest relevance signal available at this point.
|
|
104
|
+
*
|
|
105
|
+
* Returns null for a short or generic request ("review the programs", "what next?"). Ranking
|
|
106
|
+
* against those would narrow the corpus on noise, and a narrowed corpus is strictly worse than
|
|
107
|
+
* the full one when the query carries no topic — the model would lose evidence and be told the
|
|
108
|
+
* remainder was "most relevant".
|
|
109
|
+
*/
|
|
110
|
+
retrievalQuery(params) {
|
|
111
|
+
// The FIRST user message, not the last. The agent loop appends its own turns with
|
|
112
|
+
// role='user' — including action results — so by turn 3 the "latest user message" is the
|
|
113
|
+
// text of an action result, and ranking findings against that is arbitrary. Observed:
|
|
114
|
+
// turn 1 ranked against the real request, turn 3 against "Action results: …".
|
|
115
|
+
// The originating request is stable across the loop and is what the turn is about.
|
|
116
|
+
const messages = params.conversationMessages ?? [];
|
|
117
|
+
const firstUser = messages.find(m => m.role === 'user');
|
|
118
|
+
const text = typeof firstUser?.content === 'string' ? firstUser.content.trim() : '';
|
|
119
|
+
if (text.length < MIN_RETRIEVAL_QUERY_CHARS)
|
|
120
|
+
return null;
|
|
121
|
+
// A request made only of process words carries no topic to rank on.
|
|
122
|
+
const withoutFiller = text.toLowerCase().replace(GENERIC_REQUEST_WORDS, ' ').replace(/\s+/g, ' ').trim();
|
|
123
|
+
if (withoutFiller.length < MIN_RETRIEVAL_QUERY_CHARS)
|
|
124
|
+
return null;
|
|
125
|
+
return text;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Post-hook: fold the agent's mechanism into the Learning the decision already recorded.
|
|
129
|
+
*
|
|
130
|
+
* Runs after a successful step, so it sees the payload the model produced. Everything it needs
|
|
131
|
+
* beyond that comes from the database, never from the model: the program's own numbers, and
|
|
132
|
+
* the Learning row the writeback wrote.
|
|
133
|
+
*
|
|
134
|
+
* Failures here are logged and swallowed. A missing mechanism leaves a Learning that is still
|
|
135
|
+
* true and still cites its numbers; aborting the agent run over it would trade a complete
|
|
136
|
+
* record for no record.
|
|
137
|
+
*/
|
|
138
|
+
async validateSuccessNextStep(params, nextStep, currentPayload, agentRun, currentStep) {
|
|
139
|
+
const baseResult = await super.validateSuccessNextStep(params, nextStep, currentPayload, agentRun, currentStep);
|
|
140
|
+
if (baseResult.step === 'Retry')
|
|
141
|
+
return baseResult;
|
|
142
|
+
try {
|
|
143
|
+
await this.applyLearningInterpretation(currentPayload, params.contextUser, agentRun.ID);
|
|
144
|
+
}
|
|
145
|
+
catch (e) {
|
|
146
|
+
LogError(`MarketingExperimentationAgent: learning enrichment failed — ${e instanceof Error ? e.message : String(e)}`);
|
|
147
|
+
}
|
|
148
|
+
await this.attachProposals(baseResult, currentPayload, agentRun, params.contextUser);
|
|
149
|
+
return baseResult;
|
|
150
|
+
}
|
|
151
|
+
/** A turn that ends by asking the user something can still have proposed — same stamp. */
|
|
152
|
+
async validateChatNextStep(params, nextStep, currentPayload, agentRun, currentStep) {
|
|
153
|
+
const baseResult = await super.validateChatNextStep(params, nextStep, currentPayload, agentRun, currentStep);
|
|
154
|
+
await this.attachProposals(baseResult, currentPayload, agentRun, params.contextUser);
|
|
155
|
+
return baseResult;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Decides, in code, whether this run may SAVE a proposal or only DRAFT one.
|
|
159
|
+
*
|
|
160
|
+
* Inside the in-app Assistant a person is reading the proposal as it is written, so the
|
|
161
|
+
* Program row is theirs to create: the run drafts (`Propose Program` with `DraftOnly=true`)
|
|
162
|
+
* and the proposal card's Approve click commits. Everywhere else — the hourly agent, sprint
|
|
163
|
+
* end, a scheduled job — nobody is watching, and a draft nobody can see would simply be lost,
|
|
164
|
+
* so those runs commit directly and queue for approval as before.
|
|
165
|
+
*
|
|
166
|
+
* The Assistant is recognised by the app context it sends (the same signal that makes the
|
|
167
|
+
* brand picker authoritative). The template reads `proposalMode`; it does not decide it.
|
|
168
|
+
*/
|
|
169
|
+
async initializeStartingPayload(params) {
|
|
170
|
+
await super.initializeStartingPayload(params);
|
|
171
|
+
const payload = params.payload;
|
|
172
|
+
if (payload)
|
|
173
|
+
payload['proposalMode'] = this.brandFromAppContext(params) ? 'draft' : 'commit';
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Stamps what THIS run proposed onto the payload, as `proposals`.
|
|
177
|
+
*
|
|
178
|
+
* The payload is what the conversation renders as the run's artifact, and the proposal card
|
|
179
|
+
* is drawn from this list. It is built from the run's own recorded `Propose Program` action
|
|
180
|
+
* results — never from the model's account of what it did ("the prompt narrates published
|
|
181
|
+
* state"):
|
|
182
|
+
* * DRAFTED → the full validated draft rides along, because no row exists to load. The card
|
|
183
|
+
* renders it, and re-submits exactly these inputs when the user approves.
|
|
184
|
+
* * SUCCESS → a committed program; ids only, and the card loads the row live.
|
|
185
|
+
* A failed or blocked call produced no proposal and is skipped.
|
|
186
|
+
*/
|
|
187
|
+
async attachProposals(nextStep, currentPayload, agentRun, contextUser) {
|
|
188
|
+
const bag = (currentPayload ?? {});
|
|
189
|
+
try {
|
|
190
|
+
const res = await new RunView().RunView({
|
|
191
|
+
EntityName: 'MJ: AI Agent Run Steps',
|
|
192
|
+
ExtraFilter: `AgentRunID='${EscapeSQLString(agentRun.ID)}' AND StepType='Actions' AND Status='Completed' AND StepName LIKE '%Propose Program%'`,
|
|
193
|
+
Fields: ['OutputData'],
|
|
194
|
+
OrderBy: 'StepNumber ASC', ResultType: 'simple', BypassCache: true,
|
|
195
|
+
}, contextUser);
|
|
196
|
+
if (!res.Success) {
|
|
197
|
+
LogError(`MarketingExperimentationAgent: could not read this run's proposal steps — ${res.ErrorMessage}`);
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
const proposals = (res.Results ?? [])
|
|
201
|
+
.map(step => this.proposalFromStep(step.OutputData))
|
|
202
|
+
.filter((p) => p !== null);
|
|
203
|
+
if (proposals.length === 0)
|
|
204
|
+
return;
|
|
205
|
+
bag['proposals'] = proposals;
|
|
206
|
+
const next = nextStep.newPayload;
|
|
207
|
+
if (next && next !== bag)
|
|
208
|
+
next['proposals'] = proposals;
|
|
209
|
+
LogStatus(`MarketingExperimentationAgent: ${proposals.length} proposal(s) from this run attached to the payload `
|
|
210
|
+
+ `(${proposals.filter(p => p.draft).length} draft).`);
|
|
211
|
+
}
|
|
212
|
+
catch (e) {
|
|
213
|
+
LogError(`MarketingExperimentationAgent: attaching proposals failed — ${e instanceof Error ? e.message : String(e)}`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
/** One recorded `Propose Program` result → a proposal reference, or null when it produced none. */
|
|
217
|
+
proposalFromStep(outputData) {
|
|
218
|
+
if (!outputData)
|
|
219
|
+
return null;
|
|
220
|
+
let parsed;
|
|
221
|
+
try {
|
|
222
|
+
parsed = JSON.parse(outputData);
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
return null; // not JSON — not an action result this shell understands
|
|
226
|
+
}
|
|
227
|
+
const result = parsed.actionResult;
|
|
228
|
+
if (!result?.success || !Array.isArray(result.parameters))
|
|
229
|
+
return null;
|
|
230
|
+
const byType = (type) => Object.fromEntries(result.parameters.filter(p => p.Type === type && p.Value !== null && p.Value !== undefined).map(p => [p.Name, p.Value]));
|
|
231
|
+
const inputs = byType('Input');
|
|
232
|
+
const outputs = byType('Output');
|
|
233
|
+
const text = (v) => (typeof v === 'string' && v.trim() ? v : null);
|
|
234
|
+
if (result.resultCode === 'DRAFTED') {
|
|
235
|
+
const draftKey = text(outputs['DraftKey']);
|
|
236
|
+
if (!draftKey)
|
|
237
|
+
return null;
|
|
238
|
+
delete inputs['DraftOnly']; // the re-submit on Approve must COMMIT
|
|
239
|
+
return {
|
|
240
|
+
programId: null, code: null, name: text(inputs['Name']), approvalRequestId: null,
|
|
241
|
+
draft: {
|
|
242
|
+
key: draftKey,
|
|
243
|
+
inputs,
|
|
244
|
+
programTier: text(outputs['ProgramTier']),
|
|
245
|
+
programType: text(outputs['ProgramType']),
|
|
246
|
+
proposalConfidence: text(outputs['ProposalConfidence']),
|
|
247
|
+
requiresOverride: outputs['RequiresOverride'] === true,
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
const programId = text(outputs['ProgramID']);
|
|
252
|
+
if (!programId)
|
|
253
|
+
return null;
|
|
254
|
+
return {
|
|
255
|
+
programId, code: text(outputs['Code']), name: text(inputs['Name']),
|
|
256
|
+
approvalRequestId: text(outputs['ApprovalRequestID']), draft: null,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Applies the model's mechanism to the most recent Learning for the named program.
|
|
261
|
+
*
|
|
262
|
+
* No-ops silently when the payload carries no interpretation — the agent has other jobs
|
|
263
|
+
* (proposing), and only the decision-interpretation turn produces one.
|
|
264
|
+
*/
|
|
265
|
+
async applyLearningInterpretation(payload, contextUser, agentRunId) {
|
|
266
|
+
const bag = (payload ?? {});
|
|
267
|
+
const interpretation = bag[MarketingExperimentationAgent_1.INTERPRETATION_KEY];
|
|
268
|
+
const programId = bag[MarketingExperimentationAgent_1.PROGRAM_KEY];
|
|
269
|
+
if (typeof interpretation !== 'string' || !interpretation.trim())
|
|
270
|
+
return;
|
|
271
|
+
if (typeof programId !== 'string' || !programId.trim()) {
|
|
272
|
+
LogError('MarketingExperimentationAgent: an interpretation was supplied with no '
|
|
273
|
+
+ `${MarketingExperimentationAgent_1.PROGRAM_KEY} — refusing to guess which program it belongs to.`);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const rv = new RunView();
|
|
277
|
+
// The program's own numbers define what the model is allowed to cite.
|
|
278
|
+
const exp = (await rv.RunView({
|
|
279
|
+
EntityName: toMarketingEntityName('Programs'),
|
|
280
|
+
ExtraFilter: `ID='${EscapeSQLString(programId)}'`,
|
|
281
|
+
Fields: ['ID', 'Code', 'Decision', 'MetricBaseline', 'KeepThreshold', 'KillThreshold', 'IterateRangeMin', 'IterateRangeMax'],
|
|
282
|
+
MaxRows: 1, ResultType: 'simple', BypassCache: true,
|
|
283
|
+
}, contextUser)).Results?.[0];
|
|
284
|
+
if (!exp) {
|
|
285
|
+
LogError(`MarketingExperimentationAgent: program ${programId} not found; interpretation dropped.`);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (!exp.Decision) {
|
|
289
|
+
LogError(`MarketingExperimentationAgent: program ${exp.Code ?? programId} has no recorded Decision. `
|
|
290
|
+
+ 'An interpretation cannot precede the decision it interprets — dropped.');
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
// The Learning the writeback already created. Read fresh: it was written moments ago.
|
|
294
|
+
const learningRow = (await rv.RunView({
|
|
295
|
+
EntityName: toMarketingEntityName('Agent Learnings'),
|
|
296
|
+
ExtraFilter: `RelatedProgramID='${EscapeSQLString(programId)}'`,
|
|
297
|
+
Fields: ['ID', 'Finding'],
|
|
298
|
+
OrderBy: '__mj_CreatedAt DESC', MaxRows: 1, ResultType: 'simple', BypassCache: true,
|
|
299
|
+
}, contextUser)).Results?.[0];
|
|
300
|
+
if (!learningRow) {
|
|
301
|
+
LogError(`MarketingExperimentationAgent: no Learning recorded for ${exp.Code ?? programId} yet; `
|
|
302
|
+
+ 'nothing to enrich. The decision writeback runs first.');
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
// Observed values live on the segment results the observation path wrote.
|
|
306
|
+
const observed = (await rv.RunView({
|
|
307
|
+
EntityName: toMarketingEntityName('Program Segment Results'),
|
|
308
|
+
ExtraFilter: `ProgramID='${EscapeSQLString(programId)}'`,
|
|
309
|
+
Fields: ['ObservedMetric', 'ConversionsCount'], ResultType: 'simple', BypassCache: true,
|
|
310
|
+
}, contextUser)).Results ?? [];
|
|
311
|
+
const allowedNumbers = [
|
|
312
|
+
exp.MetricBaseline, exp.KeepThreshold, exp.KillThreshold, exp.IterateRangeMin, exp.IterateRangeMax,
|
|
313
|
+
...observed.flatMap(o => [o.ObservedMetric, o.ConversionsCount]),
|
|
314
|
+
];
|
|
315
|
+
const result = enrichFinding(learningRow.Finding ?? '', interpretation, {
|
|
316
|
+
decision: this.toDecisionOutcome(exp.Decision),
|
|
317
|
+
allowedNumbers,
|
|
318
|
+
});
|
|
319
|
+
if (!result.enriched) {
|
|
320
|
+
// Not an error — the guard doing its job. Logged loudly because a repeatedly-rejected
|
|
321
|
+
// interpretation means the prompt needs fixing, not the guard.
|
|
322
|
+
LogStatus(`MarketingExperimentationAgent: interpretation REJECTED for ${exp.Code ?? programId} `
|
|
323
|
+
+ `(${result.problems.join('; ')}). The factual finding stands unchanged.`);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
const md = new Metadata();
|
|
327
|
+
const learning = await md.GetEntityObject(toMarketingEntityName('Agent Learnings'), contextUser);
|
|
328
|
+
if (!await learning.Load(learningRow.ID)) {
|
|
329
|
+
LogError(`MarketingExperimentationAgent: could not load Learning ${learningRow.ID}.`);
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
learning.Finding = result.finding;
|
|
333
|
+
// Source moves off 'program' only when an agent actually contributed: 'analysis' is the
|
|
334
|
+
// value list's slot for agent-derived reasoning, and it keeps agent-enriched findings
|
|
335
|
+
// distinguishable from purely mechanical ones.
|
|
336
|
+
learning.Source = 'analysis';
|
|
337
|
+
if (!await learning.Save()) {
|
|
338
|
+
LogError(`MarketingExperimentationAgent: Learning ${learningRow.ID} save failed — `
|
|
339
|
+
+ `${learning.LatestResult?.CompleteMessage ?? 'unknown'}`);
|
|
340
|
+
return;
|
|
341
|
+
}
|
|
342
|
+
LogStatus(`MarketingExperimentationAgent: enriched Learning ${learningRow.ID} for ${exp.Code ?? programId} `
|
|
343
|
+
+ `(agent run ${agentRunId}).`);
|
|
344
|
+
}
|
|
345
|
+
/**
|
|
346
|
+
* `Program.Decision` is title-case ('Keep'); the writeback rules are upper-case ('KEEP').
|
|
347
|
+
* The two columns genuinely disagree on casing, so the mapping is explicit rather than a
|
|
348
|
+
* `toUpperCase()` that would quietly produce an invalid value for anything unexpected.
|
|
349
|
+
*/
|
|
350
|
+
toDecisionOutcome(decision) {
|
|
351
|
+
switch (decision.trim().toLowerCase()) {
|
|
352
|
+
case 'keep': return 'KEEP';
|
|
353
|
+
case 'iterate': return 'ITERATE';
|
|
354
|
+
case 'kill': return 'KILL';
|
|
355
|
+
case 'graduate': return 'GRADUATE';
|
|
356
|
+
default:
|
|
357
|
+
// Treat an unknown decision as the most restrictive: ITERATE permits no
|
|
358
|
+
// outcome claim at all, so a mismatched interpretation gets rejected.
|
|
359
|
+
LogError(`MarketingExperimentationAgent: unrecognised Decision "${decision}" — `
|
|
360
|
+
+ 'treating as ITERATE so no outcome claim is licensed.');
|
|
361
|
+
return 'ITERATE';
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
MarketingExperimentationAgent = MarketingExperimentationAgent_1 = __decorate([
|
|
366
|
+
RegisterClass(BaseAgent, 'MarketingExperimentationAgent')
|
|
367
|
+
], MarketingExperimentationAgent);
|
|
368
|
+
export { MarketingExperimentationAgent };
|
|
369
|
+
/** Anti-tree-shaking loader — the @RegisterClass above is a side effect. */
|
|
370
|
+
export function LoadMarketingExperimentationAgent() { }
|
|
371
|
+
//# sourceMappingURL=MarketingExperimentationAgent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarketingExperimentationAgent.js","sourceRoot":"","sources":["../../src/agents/MarketingExperimentationAgent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { BaseMarketingAgent } from './BaseMarketingAgent.js';
|
|
2
|
+
/**
|
|
3
|
+
* Marketing Operations Agent — driver class (PRD v3 S7 item 4 / readiness follow-through).
|
|
4
|
+
*
|
|
5
|
+
* The `MJ: AI Agents` row for the Operations Agent declared no DriverClass at all, so MJ's
|
|
6
|
+
* ClassFactory instantiated plain `BaseAgent` and NONE of the marketing base-class doctrine
|
|
7
|
+
* applied to the hourly loop: no brand self-resolution from the caller's grants, no payload
|
|
8
|
+
* bootstrap (`brandName`/`companyId`), no authorized-brand disambiguation. The same silent
|
|
9
|
+
* fallback had already bitten MarketingStrategyOnboardingAgent and
|
|
10
|
+
* MarketingExperimentationAgent before their driver classes were written — this closes the
|
|
11
|
+
* last gap in the set.
|
|
12
|
+
*
|
|
13
|
+
* Deliberately THIN. The Operations Agent's work is tool calls (Refresh Program Status, Close
|
|
14
|
+
* Due Sprints, Start Due Sprints, Sync Marketing Data, Get Program Context …), and every one of
|
|
15
|
+
* those actions enforces its own brand/role gate server-side — the doctrine this class needs is
|
|
16
|
+
* exactly what {@link BaseMarketingAgent} centralizes, nothing more. Numbers and dates stay
|
|
17
|
+
* owned by code inside the actions; the loop narrates and sequences. When the ops loop grows a
|
|
18
|
+
* flow-critical outcome of its own (the Experimentation agent's learning post-hook is the
|
|
19
|
+
* precedent), it gets a post-hook here — not an optional tool the model may forget.
|
|
20
|
+
*/
|
|
21
|
+
export declare class MarketingOperationsAgent extends BaseMarketingAgent {
|
|
22
|
+
}
|
|
23
|
+
export declare function LoadMarketingOperationsAgent(): void;
|
|
24
|
+
//# sourceMappingURL=MarketingOperationsAgent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarketingOperationsAgent.d.ts","sourceRoot":"","sources":["../../src/agents/MarketingOperationsAgent.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBACa,wBAAyB,SAAQ,kBAAkB;CAC/D;AAED,wBAAgB,4BAA4B,SAAK"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
8
|
+
import { BaseAgent } from '@memberjunction/ai-agents';
|
|
9
|
+
import { BaseMarketingAgent } from './BaseMarketingAgent.js';
|
|
10
|
+
/**
|
|
11
|
+
* Marketing Operations Agent — driver class (PRD v3 S7 item 4 / readiness follow-through).
|
|
12
|
+
*
|
|
13
|
+
* The `MJ: AI Agents` row for the Operations Agent declared no DriverClass at all, so MJ's
|
|
14
|
+
* ClassFactory instantiated plain `BaseAgent` and NONE of the marketing base-class doctrine
|
|
15
|
+
* applied to the hourly loop: no brand self-resolution from the caller's grants, no payload
|
|
16
|
+
* bootstrap (`brandName`/`companyId`), no authorized-brand disambiguation. The same silent
|
|
17
|
+
* fallback had already bitten MarketingStrategyOnboardingAgent and
|
|
18
|
+
* MarketingExperimentationAgent before their driver classes were written — this closes the
|
|
19
|
+
* last gap in the set.
|
|
20
|
+
*
|
|
21
|
+
* Deliberately THIN. The Operations Agent's work is tool calls (Refresh Program Status, Close
|
|
22
|
+
* Due Sprints, Start Due Sprints, Sync Marketing Data, Get Program Context …), and every one of
|
|
23
|
+
* those actions enforces its own brand/role gate server-side — the doctrine this class needs is
|
|
24
|
+
* exactly what {@link BaseMarketingAgent} centralizes, nothing more. Numbers and dates stay
|
|
25
|
+
* owned by code inside the actions; the loop narrates and sequences. When the ops loop grows a
|
|
26
|
+
* flow-critical outcome of its own (the Experimentation agent's learning post-hook is the
|
|
27
|
+
* precedent), it gets a post-hook here — not an optional tool the model may forget.
|
|
28
|
+
*/
|
|
29
|
+
let MarketingOperationsAgent = class MarketingOperationsAgent extends BaseMarketingAgent {
|
|
30
|
+
};
|
|
31
|
+
MarketingOperationsAgent = __decorate([
|
|
32
|
+
RegisterClass(BaseAgent, 'MarketingOperationsAgent')
|
|
33
|
+
], MarketingOperationsAgent);
|
|
34
|
+
export { MarketingOperationsAgent };
|
|
35
|
+
export function LoadMarketingOperationsAgent() { }
|
|
36
|
+
//# sourceMappingURL=MarketingOperationsAgent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarketingOperationsAgent.js","sourceRoot":"","sources":["../../src/agents/MarketingOperationsAgent.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;GAkBG;AAEI,IAAM,wBAAwB,GAA9B,MAAM,wBAAyB,SAAQ,kBAAkB;CAC/D,CAAA;AADY,wBAAwB;IADpC,aAAa,CAAC,SAAS,EAAE,0BAA0B,CAAC;GACxC,wBAAwB,CACpC;;AAED,MAAM,UAAU,4BAA4B,KAAI,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BaseMarketingAgent } from './BaseMarketingAgent.js';
|
|
2
|
+
/**
|
|
3
|
+
* Marketing Podcast Ingestion Agent — driver class (Content Engine PRD, Phase A row A2).
|
|
4
|
+
*
|
|
5
|
+
* The `MJ: AI Agents` row named this class but nothing defined it, so MJ's ClassFactory fell
|
|
6
|
+
* back to plain `BaseAgent` — the same silent fault that bit the Onboarding, Experimentation and
|
|
7
|
+
* Operations agents in turn: no brand self-resolution from the caller's grants or the app
|
|
8
|
+
* context, no payload bootstrap (`brandName` / `companyId`), no authorized-brand disambiguation.
|
|
9
|
+
* With Content's "Ingest now" and the per-brand Ingest-sources job about to run this agent, the
|
|
10
|
+
* brand must come from the run's context, never from a question.
|
|
11
|
+
*
|
|
12
|
+
* Deliberately THIN, like the Operations agent. The ingestion work is tool calls (Fetch Podcast
|
|
13
|
+
* From RSS, Intake Podcast From Box, Diarize Podcast Episode, Transcribe Audio …) and every one
|
|
14
|
+
* of them enforces its own brand gate server-side; the doctrine this class needs is exactly what
|
|
15
|
+
* {@link BaseMarketingAgent} centralizes. Idempotency lives in the actions and, for generation,
|
|
16
|
+
* in the pipeline's final-save check (CE-7) — not in the narration here.
|
|
17
|
+
*/
|
|
18
|
+
export declare class MarketingPodcastIngestionAgent extends BaseMarketingAgent {
|
|
19
|
+
}
|
|
20
|
+
export declare function LoadMarketingPodcastIngestionAgent(): void;
|
|
21
|
+
//# sourceMappingURL=MarketingPodcastIngestionAgent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarketingPodcastIngestionAgent.d.ts","sourceRoot":"","sources":["../../src/agents/MarketingPodcastIngestionAgent.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D;;;;;;;;;;;;;;;GAeG;AACH,qBACa,8BAA+B,SAAQ,kBAAkB;CACrE;AAED,wBAAgB,kCAAkC,SAAK"}
|