@memberjunction/cli 6.1.2 → 6.2.0-edge.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/README.md +18 -7
- package/dist/commands/agent/init.d.ts +23 -0
- package/dist/commands/agent/init.d.ts.map +1 -0
- package/dist/commands/agent/init.js +222 -0
- package/dist/commands/agent/init.js.map +1 -0
- package/dist/commands/doctor/index.d.ts +6 -4
- package/dist/commands/doctor/index.d.ts.map +1 -1
- package/dist/commands/doctor/index.js +43 -18
- package/dist/commands/doctor/index.js.map +1 -1
- package/dist/commands/test/scripts.d.ts +13 -0
- package/dist/commands/test/scripts.d.ts.map +1 -0
- package/dist/commands/test/scripts.js +50 -0
- package/dist/commands/test/scripts.js.map +1 -0
- package/dist/init-templates/citizen-builder/.agents/skills/new-agent/SKILL.md +66 -0
- package/dist/init-templates/citizen-builder/.agents/skills/package-agent/SKILL.md +69 -0
- package/dist/init-templates/citizen-builder/.agents/skills/test-agent/SKILL.md +61 -0
- package/dist/init-templates/citizen-builder/.claude/skills/new-agent/SKILL.md +66 -0
- package/dist/init-templates/citizen-builder/.claude/skills/package-agent/SKILL.md +69 -0
- package/dist/init-templates/citizen-builder/.claude/skills/test-agent/SKILL.md +61 -0
- package/dist/init-templates/citizen-builder/.env.example +30 -0
- package/dist/init-templates/citizen-builder/AGENTS.md +331 -0
- package/dist/init-templates/citizen-builder/README.md +259 -0
- package/dist/init-templates/citizen-builder/docker/Dockerfile +16 -0
- package/dist/init-templates/citizen-builder/docker-compose.yml +59 -0
- package/dist/init-templates/citizen-builder/docs/ENTERPRISE_ORG_SETUP.md +73 -0
- package/dist/init-templates/citizen-builder/docs/PROMOTION_GUIDE.md +70 -0
- package/dist/init-templates/citizen-builder/metadata/.mj-sync.json +7 -0
- package/dist/init-templates/citizen-builder/metadata/agents/.customer-insight-agent.json +55 -0
- package/dist/init-templates/citizen-builder/metadata/agents/.mj-sync.json +45 -0
- package/dist/init-templates/citizen-builder/metadata/prompts/.customer-insight-prompt.json +15 -0
- package/dist/init-templates/citizen-builder/metadata/prompts/.mj-sync.json +45 -0
- package/dist/init-templates/citizen-builder/metadata/prompts/templates/customer-insight.template.md +18 -0
- package/dist/init-templates/citizen-builder/scripts/bootstrap.sh +47 -0
- package/dist/init-templates/citizen-builder/scripts/docker-entrypoint.sh +184 -0
- package/dist/init-templates/citizen-builder/scripts/generate-capabilities.sh +74 -0
- package/dist/init-templates/citizen-builder/scripts/query-run-history.sh +34 -0
- package/dist/init-templates/citizen-builder/scripts/sync-metadata.sh +14 -0
- package/dist/init-templates/remote-mj/README.md +4 -4
- package/oclif.manifest.json +271 -98
- package/package.json +22 -22
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Enterprise Organization Setup: Real Schemas & Business Context
|
|
2
|
+
|
|
3
|
+
This document explains how enterprise organizations—such as **Blue Cypress (BC)**—configure the MemberJunction Citizen Agent Builder so business users build agents against their **real entity schemas and business relationships** instead of generic defaults.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. The Two-App Architecture
|
|
8
|
+
|
|
9
|
+
To provide an accurate, realistic authoring environment without exposing production customer data to personal machines, organizations publish two Open Apps:
|
|
10
|
+
|
|
11
|
+
| Application | Description | Carries |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| **`<org>-platform`** (e.g. `bc-platform`) | Core schema & business logic | Custom entities, fields, relationships, standard actions, and queries. |
|
|
14
|
+
| **`<org>-sampledata`** (e.g. `bc-sampledata`) | Realistic synthetic data | Loom-generated synthetic records mirroring production shapes and relational integrity. Depends on `<org>-platform`. |
|
|
15
|
+
|
|
16
|
+
When a citizen builder boots their environment and installs `<org>-sampledata`, MemberJunction's Open App dependency engine automatically resolves and installs `<org>-platform` leaf-first.
|
|
17
|
+
|
|
18
|
+
### Why This Model Works:
|
|
19
|
+
1. **Identical Entity Shapes:** Entity and field names match production exactly. An agent written against `bc-sampledata` works on production without renaming a single field or query.
|
|
20
|
+
2. **Zero PII Risk:** The data is 100% synthetic by construction. Compliance and security reviews pass automatically.
|
|
21
|
+
3. **Seamless Promotion:** Promotion is simply deploying the agent's metadata to the production instance; no code rewrites or schema remapping are needed.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 2. Configuration for Citizen Builders
|
|
26
|
+
|
|
27
|
+
### Option A: Private GitHub Repository Access (Recommended)
|
|
28
|
+
If your organization hosts `<org>-sampledata` in a private GitHub organization (e.g. `github.com/BlueCypress/`):
|
|
29
|
+
|
|
30
|
+
1. Provide the user with a fine-grained, read-only GitHub Personal Access Token (PAT) with `Contents: Read` permission on the sample data and platform repositories.
|
|
31
|
+
2. In the user's `.env`:
|
|
32
|
+
```bash
|
|
33
|
+
# Enterprise Open App Target
|
|
34
|
+
OPEN_APP_INSTALL_URL=https://github.com/BlueCypress/bc-sampledata
|
|
35
|
+
|
|
36
|
+
# Read-only GitHub PAT for private repo authentication
|
|
37
|
+
GITHUB_TOKEN=ghp_exampleTokenWithReadOnlyAccess
|
|
38
|
+
```
|
|
39
|
+
3. Run the bootstrap script:
|
|
40
|
+
```bash
|
|
41
|
+
docker compose exec api /work/scripts/bootstrap.sh
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Option B: Local Directory Mount (Zero Token)
|
|
45
|
+
If the user or team already has a local checkout of the platform app on their machine:
|
|
46
|
+
1. Create a `docker-compose.override.yml`:
|
|
47
|
+
```yaml
|
|
48
|
+
services:
|
|
49
|
+
api:
|
|
50
|
+
volumes:
|
|
51
|
+
- /path/to/local/bc-platform:/work/apps/bc-platform:ro
|
|
52
|
+
```
|
|
53
|
+
2. Run `mj app install /work/apps/bc-platform` inside the container.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 3. Automated Capabilities Cataloging
|
|
58
|
+
|
|
59
|
+
Once your organization's Open App is installed, run:
|
|
60
|
+
```bash
|
|
61
|
+
./scripts/generate-capabilities.sh
|
|
62
|
+
```
|
|
63
|
+
This queries your local database's entity and action catalogs to update `CAPABILITIES.md`. Your coding agent immediately learns every custom entity, field, and action specific to your company (e.g. `BC: Association Members`, `BC: Committee Terms`, `BC: Invoices`).
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 4. Packaging and Upstream Release of Sample Data
|
|
68
|
+
|
|
69
|
+
When updating your organization's synthetic dataset:
|
|
70
|
+
1. Generate synthetic records using Loom.
|
|
71
|
+
2. Push them to a staging database using `mj sync push`.
|
|
72
|
+
3. Capture the differential SQL emitted by `packages/MetadataSync/src/lib/sql-logger.ts` as the next `V<timestamp>__v<version>_Metadata_Sync.sql` migration in `<org>-sampledata`.
|
|
73
|
+
4. Publish a release of `<org>-sampledata`. All citizen builders will receive the updated synthetic records on their next bootstrap.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Promotion & Governance Guide: Reviewing Packaged Agents
|
|
2
|
+
|
|
3
|
+
This guide is for MemberJunction platform administrators, team leads, and review boards responsible for evaluating and deploying agents authored via the Citizen Agent Builder.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. What Arrives at Promotion
|
|
8
|
+
|
|
9
|
+
A citizen builder submits an export archive (e.g. `dist/InvoiceAuditAgent-package.zip`), which contains:
|
|
10
|
+
|
|
11
|
+
1. **`AGENT_MANIFEST.md`**: An executive summary describing:
|
|
12
|
+
- What the agent does and who built it.
|
|
13
|
+
- Classification: **Tier 1 (Declarative)** vs **Tier 2 (Runtime Action)**.
|
|
14
|
+
- Data Footprint: Explicit list of entities read and entities modified.
|
|
15
|
+
- Sample Execution Receipt: Verification trace from a test run.
|
|
16
|
+
2. **Metadata Files**:
|
|
17
|
+
- `metadata/agents/.*<name>*.json`
|
|
18
|
+
- `metadata/prompts/.*<name>*.json`
|
|
19
|
+
- `metadata/prompts/templates/<name>*.md`
|
|
20
|
+
- (If Tier 2) `metadata/actions/.*<name>*.json`
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## 2. The Review Process
|
|
25
|
+
|
|
26
|
+
### Tier 1 (Declarative Agents) — Fast Track (5-Minute Review)
|
|
27
|
+
Tier 1 agents contain **zero executable code** and **zero schema changes**. Reviewing them is straightforward:
|
|
28
|
+
|
|
29
|
+
1. **Check Defaults in Manifest**:
|
|
30
|
+
- `ModelSelectionMode` is `"Agent Type"` (no hardcoded models).
|
|
31
|
+
- `ExposeAsAction` is `false` (unless a valid business rationale is documented).
|
|
32
|
+
2. **Scan Prompts**:
|
|
33
|
+
- Verify no credentials, tokens, or raw SQL queries are embedded in prompt templates.
|
|
34
|
+
- Verify no hardcoded record IDs or personal names are used.
|
|
35
|
+
3. **Approve**:
|
|
36
|
+
- Tier 1 submissions that satisfy these checks can be approved and imported immediately.
|
|
37
|
+
|
|
38
|
+
### Tier 2 (Runtime Actions) — Code Review Gate
|
|
39
|
+
Tier 2 agents include custom JavaScript actions running in the MemberJunction sandboxed runtime:
|
|
40
|
+
|
|
41
|
+
1. **Review JavaScript Logic**:
|
|
42
|
+
- Inspect the code inside the action's metadata definition.
|
|
43
|
+
- Ensure the logic is deterministic, handles errors, and contains no obfuscated operations or network calls.
|
|
44
|
+
2. **Review & Narrow Permissions**:
|
|
45
|
+
- Verify that `allowedEntities` is an explicit, minimal list of required entities.
|
|
46
|
+
- **Reject any submission with `allowAnyEntity: true` or wildcard entity grants.**
|
|
47
|
+
3. **Decide Graduation**:
|
|
48
|
+
- **Keep as Runtime Action**: Approve the action metadata for deployment as sandboxed JS.
|
|
49
|
+
- **Promote to Package**: If the action is mission-critical or widely reused, have an engineer reimplement it as a strongly-typed TypeScript action in an `@mj-biz-apps/*` package.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 3. Deploying the Agent
|
|
54
|
+
|
|
55
|
+
### Option 1: Commit to the Organization's Platform Repo (Recommended)
|
|
56
|
+
1. Extract the metadata files into your organization's repository (e.g. `bc-platform/metadata/`).
|
|
57
|
+
2. Commit and push the changes:
|
|
58
|
+
```bash
|
|
59
|
+
git add metadata/
|
|
60
|
+
git commit -m "feat(agents): add InvoiceAuditAgent from citizen builder"
|
|
61
|
+
git push
|
|
62
|
+
```
|
|
63
|
+
3. Your CI/CD deployment pipeline will push the metadata to staging and production.
|
|
64
|
+
|
|
65
|
+
### Option 2: Direct Sync Push to Target Instance
|
|
66
|
+
If deploying directly to a staging or production instance via CLI:
|
|
67
|
+
```bash
|
|
68
|
+
mj sync push --dir /path/to/extracted/metadata
|
|
69
|
+
```
|
|
70
|
+
The agent is now active and ready for end users.
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"fields": {
|
|
4
|
+
"Name": "Customer Insight Specialist",
|
|
5
|
+
"CategoryID": "@lookup:MJ: AI Agent Categories.Name=Assistant",
|
|
6
|
+
"Description": "Deterministic flow agent that summarizes customer activity, evaluates account standing, and suggests next actions.",
|
|
7
|
+
"TypeID": "@lookup:MJ: AI Agent Types.Name=Flow",
|
|
8
|
+
"Status": "Active",
|
|
9
|
+
"ExecutionOrder": 0,
|
|
10
|
+
"ExposeAsAction": false,
|
|
11
|
+
"IconClass": "mj-icon-user-check",
|
|
12
|
+
"ArtifactCreationMode": "None",
|
|
13
|
+
"PayloadDownstreamPaths": "*",
|
|
14
|
+
"PayloadUpstreamPaths": "*",
|
|
15
|
+
"EnableContextCompression": false,
|
|
16
|
+
"ModelSelectionMode": "Agent Type"
|
|
17
|
+
},
|
|
18
|
+
"relatedEntities": {
|
|
19
|
+
"MJ: AI Agent Prompts": [
|
|
20
|
+
{
|
|
21
|
+
"fields": {
|
|
22
|
+
"AgentID": "@parent:ID",
|
|
23
|
+
"PromptID": "@lookup:MJ: AI Prompts.Name=Customer Insight Specialist Prompt",
|
|
24
|
+
"Status": "Active",
|
|
25
|
+
"ExecutionOrder": 1
|
|
26
|
+
},
|
|
27
|
+
"primaryKey": {
|
|
28
|
+
"ID": "E9A0C381-645F-4D2A-883F-E19C69D3B511"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"MJ: AI Agent Steps": [
|
|
33
|
+
{
|
|
34
|
+
"fields": {
|
|
35
|
+
"AgentID": "@parent:ID",
|
|
36
|
+
"Name": "Generate Customer Insights",
|
|
37
|
+
"Description": "Evaluates account data using the Customer Insight Specialist Prompt",
|
|
38
|
+
"StepType": "Prompt",
|
|
39
|
+
"StartingStep": true,
|
|
40
|
+
"PromptID": "@lookup:MJ: AI Prompts.Name=Customer Insight Specialist Prompt",
|
|
41
|
+
"Status": "Active",
|
|
42
|
+
"PositionX": 100,
|
|
43
|
+
"PositionY": 100
|
|
44
|
+
},
|
|
45
|
+
"primaryKey": {
|
|
46
|
+
"ID": "D2E49B18-091A-4832-B81E-A38C91307D55"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
},
|
|
51
|
+
"primaryKey": {
|
|
52
|
+
"ID": "A7F01234-8899-4A1B-89E2-7722BCDEF001"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
]
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"entity": "MJ: AI Agents",
|
|
3
|
+
"filePattern": "**/.*.json",
|
|
4
|
+
"defaults": {
|
|
5
|
+
"TypeID": "@lookup:MJ: AI Agent Types.Name=Flow",
|
|
6
|
+
"ModelSelectionMode": "Agent Type",
|
|
7
|
+
"ExposeAsAction": false,
|
|
8
|
+
"Status": "Active"
|
|
9
|
+
},
|
|
10
|
+
"pull": {
|
|
11
|
+
"createNewFileIfNotFound": true,
|
|
12
|
+
"newFileName": ".agents.json",
|
|
13
|
+
"appendRecordsToExistingFile": true,
|
|
14
|
+
"updateExistingRecords": true,
|
|
15
|
+
"preserveFields": [],
|
|
16
|
+
"excludeFields": [],
|
|
17
|
+
"mergeStrategy": "merge",
|
|
18
|
+
"backupBeforeUpdate": true,
|
|
19
|
+
"backupDirectory": ".backups",
|
|
20
|
+
"lookupFields": {
|
|
21
|
+
"TypeID": {
|
|
22
|
+
"entity": "MJ: AI Agent Types",
|
|
23
|
+
"field": "Name"
|
|
24
|
+
},
|
|
25
|
+
"CategoryID": {
|
|
26
|
+
"entity": "MJ: AI Agent Categories",
|
|
27
|
+
"field": "Name"
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"relatedEntities": {
|
|
31
|
+
"MJ: AI Agent Prompts": {
|
|
32
|
+
"entity": "MJ: AI Agent Prompts",
|
|
33
|
+
"foreignKey": "AgentID"
|
|
34
|
+
},
|
|
35
|
+
"MJ: AI Agent Actions": {
|
|
36
|
+
"entity": "MJ: AI Agent Actions",
|
|
37
|
+
"foreignKey": "AgentID"
|
|
38
|
+
},
|
|
39
|
+
"MJ: AI Agent Steps": {
|
|
40
|
+
"entity": "MJ: AI Agent Steps",
|
|
41
|
+
"foreignKey": "AgentID"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"fields": {
|
|
4
|
+
"Name": "Customer Insight Specialist Prompt",
|
|
5
|
+
"Description": "Analyzes customer profile data and recent orders to provide executive account insights.",
|
|
6
|
+
"CategoryID": "@lookup:MJ: AI Prompt Categories.Name=Agent Type System Prompts",
|
|
7
|
+
"TypeID": "@lookup:MJ: AI Prompt Types.Name=Chat",
|
|
8
|
+
"Status": "Active",
|
|
9
|
+
"TemplateText": "@file:templates/customer-insight.template.md"
|
|
10
|
+
},
|
|
11
|
+
"primaryKey": {
|
|
12
|
+
"ID": "B1C90D1A-9321-4E18-912A-6844917B3C10"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
]
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"entity": "MJ: AI Prompts",
|
|
3
|
+
"filePattern": "**/.*.json",
|
|
4
|
+
"defaults": {
|
|
5
|
+
"CategoryID": "@lookup:MJ: AI Prompt Categories.Name=Agent Type System Prompts?create&Description=Prompts for Custom Agents",
|
|
6
|
+
"TypeID": "@lookup:MJ: AI Prompt Types.Name=Chat"
|
|
7
|
+
},
|
|
8
|
+
"ignoreDirectories": [
|
|
9
|
+
"output",
|
|
10
|
+
"templates"
|
|
11
|
+
],
|
|
12
|
+
"pull": {
|
|
13
|
+
"createNewFileIfNotFound": true,
|
|
14
|
+
"newFileName": ".prompts.json",
|
|
15
|
+
"appendRecordsToExistingFile": true,
|
|
16
|
+
"updateExistingRecords": true,
|
|
17
|
+
"ignoreNullFields": true,
|
|
18
|
+
"ignoreVirtualFields": true,
|
|
19
|
+
"preserveFields": [
|
|
20
|
+
"TemplateText"
|
|
21
|
+
],
|
|
22
|
+
"excludeFields": [
|
|
23
|
+
"TemplateID"
|
|
24
|
+
],
|
|
25
|
+
"mergeStrategy": "merge",
|
|
26
|
+
"backupBeforeUpdate": true,
|
|
27
|
+
"backupDirectory": ".backups",
|
|
28
|
+
"externalizeFields": [
|
|
29
|
+
{
|
|
30
|
+
"field": "TemplateText",
|
|
31
|
+
"pattern": "@file:templates/{Name}.template.md"
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
"lookupFields": {
|
|
35
|
+
"CategoryID": {
|
|
36
|
+
"entity": "MJ: AI Prompt Categories",
|
|
37
|
+
"field": "Name"
|
|
38
|
+
},
|
|
39
|
+
"TypeID": {
|
|
40
|
+
"entity": "MJ: AI Prompt Types",
|
|
41
|
+
"field": "Name"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
package/dist/init-templates/citizen-builder/metadata/prompts/templates/customer-insight.template.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Customer Insight Specialist Prompt
|
|
2
|
+
|
|
3
|
+
You are an expert customer account analyst. Your goal is to review customer profile data and order history, then synthesize a concise executive summary with actionable recommendations.
|
|
4
|
+
|
|
5
|
+
## Instructions
|
|
6
|
+
1. Analyze the customer account details, active status, and recent activity.
|
|
7
|
+
2. Review any open orders or pending balances.
|
|
8
|
+
3. Formulate 3 key insights:
|
|
9
|
+
- Account Health (engagement level and standing)
|
|
10
|
+
- Value / Purchase Pattern (frequent categories, average volume)
|
|
11
|
+
- Recommended Next Action (e.g. follow-up call, cross-sell recommendation, renewal notice)
|
|
12
|
+
4. Maintain a professional, objective tone. Do not fabricate details not present in the input.
|
|
13
|
+
|
|
14
|
+
## Output Format
|
|
15
|
+
Deliver your response formatted cleanly with the following markdown sections:
|
|
16
|
+
- **Executive Summary**
|
|
17
|
+
- **Key Metrics & Observations**
|
|
18
|
+
- **Actionable Recommendations**
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ==============================================================================
|
|
3
|
+
# Citizen Agent Builder - Environment Bootstrap Script
|
|
4
|
+
# Runs inside the MJAPI container or via:
|
|
5
|
+
# docker compose exec api /work/scripts/bootstrap.sh
|
|
6
|
+
# ==============================================================================
|
|
7
|
+
set -e
|
|
8
|
+
|
|
9
|
+
echo "========================================================"
|
|
10
|
+
echo " Starting MemberJunction Citizen Builder Bootstrap"
|
|
11
|
+
echo "========================================================"
|
|
12
|
+
|
|
13
|
+
cd /app
|
|
14
|
+
|
|
15
|
+
# 1. Run core migrations
|
|
16
|
+
echo "[1/4] Ensuring core MemberJunction database migrations are applied..."
|
|
17
|
+
mj migrate
|
|
18
|
+
|
|
19
|
+
# 2. Install Open App (More Cheese by default, or Org-specific app)
|
|
20
|
+
APP_URL="${OPEN_APP_INSTALL_URL:-https://github.com/MemberJunction/more-cheese}"
|
|
21
|
+
echo "[2/4] Installing business context Open App: $APP_URL..."
|
|
22
|
+
|
|
23
|
+
if [ -n "$GITHUB_TOKEN" ]; then
|
|
24
|
+
# Inject token into GitHub URL if private repo
|
|
25
|
+
AUTH_APP_URL=$(echo "$APP_URL" | sed -E "s|https://github.com/|https://$GITHUB_TOKEN@github.com/|")
|
|
26
|
+
mj app install "$AUTH_APP_URL" || echo "Warning: mj app install returned non-zero, continuing..."
|
|
27
|
+
else
|
|
28
|
+
mj app install "$APP_URL" || echo "Warning: mj app install returned non-zero, continuing..."
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# 3. Generate Capabilities Catalog
|
|
32
|
+
echo "[3/4] Generating CAPABILITIES.md catalog from database..."
|
|
33
|
+
if [ -f "/work/scripts/generate-capabilities.sh" ]; then
|
|
34
|
+
bash /work/scripts/generate-capabilities.sh || echo "Warning: Capability generation skipped."
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# 4. Push local metadata
|
|
38
|
+
echo "[4/4] Pushing starter metadata to local instance..."
|
|
39
|
+
if [ -d "/work/metadata" ]; then
|
|
40
|
+
mj sync push --dir /work/metadata || echo "Initial sync completed or already up to date."
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
echo "========================================================"
|
|
44
|
+
echo " MemberJunction Citizen Builder is Ready!"
|
|
45
|
+
echo " API: http://localhost:${API_PORT:-4000}"
|
|
46
|
+
echo " Database: localhost:${DB_PORT:-1433}"
|
|
47
|
+
echo "========================================================"
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ==============================================================================
|
|
3
|
+
# MemberJunction Citizen Agent Builder - Container Entrypoint
|
|
4
|
+
# Automates first-time installation via `mj install`, database provisioning,
|
|
5
|
+
# Open App installation, and starts both MJAPI (:4000) and MJExplorer (:4200).
|
|
6
|
+
# ==============================================================================
|
|
7
|
+
set -e
|
|
8
|
+
|
|
9
|
+
echo "========================================================================"
|
|
10
|
+
echo " Starting MemberJunction Runtime Container"
|
|
11
|
+
echo "========================================================================"
|
|
12
|
+
|
|
13
|
+
DB_HOST="${DB_HOST:-sqlserver}"
|
|
14
|
+
DB_PORT="${DB_PORT:-1433}"
|
|
15
|
+
DB_PASSWORD="${DB_PASSWORD:-TestPassword123!}"
|
|
16
|
+
DB_DATABASE="${DB_DATABASE:-MemberJunction}"
|
|
17
|
+
|
|
18
|
+
# 1. Wait for SQL Server to be accessible
|
|
19
|
+
echo "Waiting for SQL Server ($DB_HOST:$DB_PORT) to be ready..."
|
|
20
|
+
until node -e "
|
|
21
|
+
const net = require('net');
|
|
22
|
+
const client = net.connect($DB_PORT, '$DB_HOST', () => {
|
|
23
|
+
client.destroy();
|
|
24
|
+
process.exit(0);
|
|
25
|
+
});
|
|
26
|
+
client.on('error', () => process.exit(1));
|
|
27
|
+
setTimeout(() => process.exit(1), 2000);
|
|
28
|
+
" 2>/dev/null; do
|
|
29
|
+
echo " Waiting for database connection..."
|
|
30
|
+
sleep 3
|
|
31
|
+
done
|
|
32
|
+
echo "SQL Server is reachable!"
|
|
33
|
+
|
|
34
|
+
cd /workspace
|
|
35
|
+
|
|
36
|
+
# 2. First-time setup: install MemberJunction if not already installed
|
|
37
|
+
if [ ! -f "/workspace/package.json" ]; then
|
|
38
|
+
echo ""
|
|
39
|
+
echo "========================================================================"
|
|
40
|
+
echo " First-Time Setup: Installing MemberJunction via 'mj install'..."
|
|
41
|
+
echo " This runs once and initializes your database, API, and Explorer."
|
|
42
|
+
echo "========================================================================"
|
|
43
|
+
|
|
44
|
+
# Generate install configuration
|
|
45
|
+
cat << EOF > /tmp/install.config.json
|
|
46
|
+
{
|
|
47
|
+
"PackageManager": "pnpm",
|
|
48
|
+
"dbUrl": "$DB_HOST",
|
|
49
|
+
"dbInstance": "",
|
|
50
|
+
"dbTrustServerCertificate": "Y",
|
|
51
|
+
"dbDatabase": "$DB_DATABASE",
|
|
52
|
+
"dbPort": $DB_PORT,
|
|
53
|
+
"codeGenLogin": "sa",
|
|
54
|
+
"codeGenPwD": "$DB_PASSWORD",
|
|
55
|
+
"mjAPILogin": "sa",
|
|
56
|
+
"mjAPIPwD": "$DB_PASSWORD",
|
|
57
|
+
"graphQLPort": 4000,
|
|
58
|
+
"authType": "Local",
|
|
59
|
+
"createNewUser": "Y",
|
|
60
|
+
"userEmail": "admin@memberjunction.org",
|
|
61
|
+
"userFirstName": "Admin",
|
|
62
|
+
"userLastName": "User",
|
|
63
|
+
"userName": "admin",
|
|
64
|
+
"openAIAPIKey": "${AI_VENDOR_API_KEY__OpenAILLM:-}",
|
|
65
|
+
"anthropicAPIKey": "${AI_VENDOR_API_KEY__AnthropicLLM:-}",
|
|
66
|
+
"geminiAPIKey": "${AI_VENDOR_API_KEY__GeminiLLM:-}"
|
|
67
|
+
}
|
|
68
|
+
EOF
|
|
69
|
+
|
|
70
|
+
# Execute headless install
|
|
71
|
+
mj install --yes --fast --config /tmp/install.config.json --dir /workspace
|
|
72
|
+
pnpm add -w @angular/compiler@21.2.22 2>/dev/null || true
|
|
73
|
+
|
|
74
|
+
# Install Open App business context (More Cheese default or custom enterprise app)
|
|
75
|
+
APP_URL="${OPEN_APP_INSTALL_URL:-https://github.com/MemberJunction/more-cheese}"
|
|
76
|
+
echo "Installing business context Open App: $APP_URL..."
|
|
77
|
+
if [ -n "$GITHUB_TOKEN" ]; then
|
|
78
|
+
AUTH_APP_URL=$(echo "$APP_URL" | sed -E "s|https://github.com/|https://$GITHUB_TOKEN@github.com/|")
|
|
79
|
+
mj app install "$AUTH_APP_URL" || echo "Notice: mj app install completed or skipped."
|
|
80
|
+
else
|
|
81
|
+
mj app install "$APP_URL" || echo "Notice: mj app install completed or skipped."
|
|
82
|
+
fi
|
|
83
|
+
|
|
84
|
+
# Generate capabilities catalog
|
|
85
|
+
if [ -f "/work/scripts/generate-capabilities.sh" ]; then
|
|
86
|
+
bash /work/scripts/generate-capabilities.sh || echo "Notice: Capabilities generation completed."
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Push starter metadata
|
|
90
|
+
if [ -d "/work/metadata" ]; then
|
|
91
|
+
mj sync push --dir /work/metadata || echo "Notice: Initial metadata push completed."
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
echo "MemberJunction installation and provisioning complete!"
|
|
95
|
+
else
|
|
96
|
+
echo "Existing MemberJunction workspace detected in /workspace."
|
|
97
|
+
# Apply any pending migrations
|
|
98
|
+
mj migrate || echo "Database migrations up to date."
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# Configure MJExplorer host binding and compiler alignment
|
|
102
|
+
if [ -f "apps/MJExplorer/package.json" ]; then
|
|
103
|
+
node -e "
|
|
104
|
+
const fs = require('fs');
|
|
105
|
+
const p = 'apps/MJExplorer/package.json';
|
|
106
|
+
const pkg = JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
107
|
+
let changed = false;
|
|
108
|
+
if (pkg.scripts && pkg.scripts.start && !pkg.scripts.start.includes('--host 0.0.0.0')) {
|
|
109
|
+
pkg.scripts.start = pkg.scripts.start.replace('ng serve', 'ng serve --host 0.0.0.0 --port 4200');
|
|
110
|
+
changed = true;
|
|
111
|
+
}
|
|
112
|
+
const cliVer = (pkg.devDependencies && pkg.devDependencies['@angular/compiler-cli']) || '21.2.22';
|
|
113
|
+
if (pkg.dependencies && pkg.dependencies['@angular/compiler'] !== cliVer) {
|
|
114
|
+
pkg.dependencies['@angular/compiler'] = cliVer;
|
|
115
|
+
changed = true;
|
|
116
|
+
}
|
|
117
|
+
if (changed) {
|
|
118
|
+
fs.writeFileSync(p, JSON.stringify(pkg, null, 2));
|
|
119
|
+
}
|
|
120
|
+
"
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# Sanitize dynamicPackages.client so non-browser packages are not bundled into MJExplorer
|
|
124
|
+
if [ -f "mj.config.cjs" ]; then
|
|
125
|
+
node -e "
|
|
126
|
+
const fs = require('fs');
|
|
127
|
+
try {
|
|
128
|
+
const config = require('./mj.config.cjs');
|
|
129
|
+
if (config.dynamicPackages && Array.isArray(config.dynamicPackages.client)) {
|
|
130
|
+
let changed = false;
|
|
131
|
+
config.dynamicPackages.client.forEach(entry => {
|
|
132
|
+
if (!entry.PackageName.endsWith('-ng') || entry.PackageName === '@mj-biz-apps/sonar-ng') {
|
|
133
|
+
if (entry.Enabled !== false) {
|
|
134
|
+
entry.Enabled = false;
|
|
135
|
+
changed = true;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
if (changed) {
|
|
140
|
+
let code = fs.readFileSync('mj.config.cjs', 'utf8');
|
|
141
|
+
const regex = /client:\s*\[[\s\S]*?\]\s*\},/m;
|
|
142
|
+
code = code.replace(regex, 'client: ' + JSON.stringify(config.dynamicPackages.client, null, 2) + '\n },');
|
|
143
|
+
fs.writeFileSync('mj.config.cjs', code);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
} catch (e) {
|
|
147
|
+
console.warn('Notice: dynamicPackages check skipped:', e.message);
|
|
148
|
+
}
|
|
149
|
+
"
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
# 3. Start MJAPI and MJExplorer services via PM2
|
|
153
|
+
echo "Starting MJAPI and MJExplorer services..."
|
|
154
|
+
pm2 delete all 2>/dev/null || true
|
|
155
|
+
|
|
156
|
+
# Start API service
|
|
157
|
+
if [ -f "package.json" ]; then
|
|
158
|
+
if grep -q "start:api" package.json; then
|
|
159
|
+
pm2 start "npm run start:api" --name mjapi
|
|
160
|
+
elif [ -d "apps/MJAPI" ]; then
|
|
161
|
+
pm2 start "cd apps/MJAPI && npm start" --name mjapi
|
|
162
|
+
else
|
|
163
|
+
pm2 start "npm start" --name mjapi
|
|
164
|
+
fi
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# Start Explorer service
|
|
168
|
+
if [ -f "package.json" ]; then
|
|
169
|
+
if grep -q "start:explorer" package.json; then
|
|
170
|
+
pm2 start "npm run start:explorer" --name mjexplorer
|
|
171
|
+
elif [ -d "apps/MJExplorer" ]; then
|
|
172
|
+
pm2 start "cd apps/MJExplorer && npm start" --name mjexplorer
|
|
173
|
+
fi
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
echo "========================================================================"
|
|
177
|
+
echo " 🎉 MemberJunction Stack is Running!"
|
|
178
|
+
echo " MJAPI: http://localhost:4000 (GraphQL & API)"
|
|
179
|
+
echo " MJExplorer: http://localhost:4200 (Web Interface)"
|
|
180
|
+
echo " Database: localhost:$DB_PORT (DB: $DB_DATABASE)"
|
|
181
|
+
echo "========================================================================"
|
|
182
|
+
|
|
183
|
+
# Keep container running and stream logs
|
|
184
|
+
exec pm2 logs
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# ==============================================================================
|
|
3
|
+
# Citizen Agent Builder - Capabilities Catalog Generator
|
|
4
|
+
# Queries the local MemberJunction database and outputs an updated CAPABILITIES.md
|
|
5
|
+
# so the local coding agent has an exact catalog of entities, actions, and agents.
|
|
6
|
+
# ==============================================================================
|
|
7
|
+
set -e
|
|
8
|
+
|
|
9
|
+
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
10
|
+
OUTPUT_FILE="$DIR/CAPABILITIES.md"
|
|
11
|
+
|
|
12
|
+
if [ -f "$DIR/.env" ]; then
|
|
13
|
+
set -a
|
|
14
|
+
source "$DIR/.env"
|
|
15
|
+
set +a
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
DB_PASSWORD="${DB_PASSWORD:-TestPassword123!}"
|
|
19
|
+
|
|
20
|
+
echo "Generating CAPABILITIES.md from database catalog..."
|
|
21
|
+
|
|
22
|
+
SQL_QUERY="
|
|
23
|
+
SET NOCOUNT ON;
|
|
24
|
+
PRINT '# System Capabilities Catalog';
|
|
25
|
+
PRINT '';
|
|
26
|
+
PRINT 'This catalog reflects the real entities, actions, and agents available in this MemberJunction instance.';
|
|
27
|
+
PRINT 'Use these exact names when authoring agent steps, action bindings, and prompt templates.';
|
|
28
|
+
PRINT '';
|
|
29
|
+
PRINT '## 1. Available Entities';
|
|
30
|
+
PRINT '| Entity Name | Description |';
|
|
31
|
+
PRINT '|---|---|';
|
|
32
|
+
SELECT '| \`' + Name + '\` | ' + REPLACE(REPLACE(COALESCE(Description, 'No description'), CHAR(13), ' '), CHAR(10), ' ') + ' |'
|
|
33
|
+
FROM [__mj].[vwEntities]
|
|
34
|
+
WHERE VirtualEntity = 0
|
|
35
|
+
ORDER BY Name ASC;
|
|
36
|
+
|
|
37
|
+
PRINT '';
|
|
38
|
+
PRINT '## 2. Available Actions (Tools)';
|
|
39
|
+
PRINT '| Action Name | Description |';
|
|
40
|
+
PRINT '|---|---|';
|
|
41
|
+
SELECT '| \`' + Name + '\` | ' + REPLACE(REPLACE(COALESCE(Description, 'No description'), CHAR(13), ' '), CHAR(10), ' ') + ' |'
|
|
42
|
+
FROM [__mj].[vwActions]
|
|
43
|
+
ORDER BY Name ASC;
|
|
44
|
+
|
|
45
|
+
PRINT '';
|
|
46
|
+
PRINT '## 3. Available Sub-Agents';
|
|
47
|
+
PRINT '| Agent Name | Type | Description |';
|
|
48
|
+
PRINT '|---|---|---|';
|
|
49
|
+
SELECT '| \`' + Name + '\` | ' + Type + ' | ' + REPLACE(REPLACE(COALESCE(Description, 'No description'), CHAR(13), ' '), CHAR(10), ' ') + ' |'
|
|
50
|
+
FROM [__mj].[vwAIAgents]
|
|
51
|
+
ORDER BY Name ASC;
|
|
52
|
+
"
|
|
53
|
+
|
|
54
|
+
docker compose exec -T sqlserver /opt/mssql-tools18/bin/sqlcmd \
|
|
55
|
+
-S localhost -U sa -P "$DB_PASSWORD" -d MemberJunction -C -No -W -w 200 \
|
|
56
|
+
-Q "$SQL_QUERY" > "$OUTPUT_FILE" 2>/dev/null || {
|
|
57
|
+
echo "Notice: Database not yet initialized; creating baseline CAPABILITIES.md"
|
|
58
|
+
cat << 'EOF' > "$OUTPUT_FILE"
|
|
59
|
+
# System Capabilities Catalog
|
|
60
|
+
|
|
61
|
+
*This catalog is automatically populated once your local database is booted and bootstrapped.*
|
|
62
|
+
|
|
63
|
+
## Available Core Actions
|
|
64
|
+
* `Send Email` - Send notification or transactional emails
|
|
65
|
+
* `Create Record` - Insert a new record into any permitted entity
|
|
66
|
+
* `Update Record` - Update an existing record by ID
|
|
67
|
+
* `Run Query` - Execute a dynamic query against entities
|
|
68
|
+
* `Get Record` - Fetch a record by primary key
|
|
69
|
+
|
|
70
|
+
Run `./scripts/bootstrap.sh` to populate the complete catalog from your installed Open App.
|
|
71
|
+
EOF
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
echo "Capabilities catalog updated at: $OUTPUT_FILE"
|