feat: Add machine token auth for Mission Control CLI
- Add mc_api_call_machine() function for MC_MACHINE_TOKEN auth - Update mc_api_call() to use machine token when available - Allows cron jobs to authenticate without cookie-based login - No breaking changes - cookie auth still works for interactive use - Also updates default API URL to production (was localhost)
This commit is contained in:
parent
62b730dae1
commit
95060930b1
@ -1,35 +1,81 @@
|
||||
import { createClient } from '@supabase/supabase-js';
|
||||
import { NextResponse } from 'next/server';
|
||||
|
||||
function getSupabaseServerClient() {
|
||||
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
|
||||
const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY;
|
||||
|
||||
if (!supabaseUrl) {
|
||||
throw new Error('Server configuration error: Missing Supabase URL');
|
||||
}
|
||||
|
||||
if (!supabaseServiceKey) {
|
||||
throw new Error('Server configuration error: Missing Supabase service key');
|
||||
}
|
||||
|
||||
return createClient(supabaseUrl, supabaseServiceKey, {
|
||||
auth: {
|
||||
autoRefreshToken: false,
|
||||
persistSession: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function POST(request: Request) {
|
||||
try {
|
||||
const supabase = getSupabaseServerClient();
|
||||
const body = await request.json();
|
||||
|
||||
const {
|
||||
title,
|
||||
content,
|
||||
type = 'markdown',
|
||||
folder = 'Research/',
|
||||
tags = ['saved', 'article'],
|
||||
description,
|
||||
size,
|
||||
} = body;
|
||||
|
||||
// Validate required fields
|
||||
if (!title || !content) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Missing required fields: title and content' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from('mission_control_documents')
|
||||
.insert({
|
||||
title,
|
||||
content,
|
||||
type,
|
||||
folder,
|
||||
tags,
|
||||
description,
|
||||
size,
|
||||
})
|
||||
.select()
|
||||
.single();
|
||||
|
||||
if (error) {
|
||||
console.error('Supabase error:', error);
|
||||
return NextResponse.json({ error: error.message }, { status: 500 });
|
||||
}
|
||||
|
||||
return NextResponse.json({ document: data }, { status: 201 });
|
||||
} catch (err: any) {
|
||||
console.error('POST /api/documents error:', err);
|
||||
return NextResponse.json(
|
||||
{ error: err.message || 'Unknown error occurred' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
// Get environment variables inside the handler (important for Vercel)
|
||||
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL;
|
||||
const supabaseServiceKey = process.env.SUPABASE_SERVICE_ROLE_KEY;
|
||||
|
||||
// Validate environment variables
|
||||
if (!supabaseUrl) {
|
||||
console.error('Missing NEXT_PUBLIC_SUPABASE_URL environment variable');
|
||||
return NextResponse.json(
|
||||
{ error: 'Server configuration error: Missing Supabase URL' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
|
||||
if (!supabaseServiceKey) {
|
||||
console.error('Missing SUPABASE_SERVICE_ROLE_KEY environment variable');
|
||||
return NextResponse.json(
|
||||
{ error: 'Server configuration error: Missing Supabase service key' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
|
||||
const supabase = createClient(supabaseUrl, supabaseServiceKey, {
|
||||
auth: {
|
||||
autoRefreshToken: false,
|
||||
persistSession: false,
|
||||
},
|
||||
});
|
||||
const supabase = getSupabaseServerClient();
|
||||
|
||||
const { data, error } = await supabase
|
||||
.from('mission_control_documents')
|
||||
@ -50,3 +96,53 @@ export async function GET() {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(request: Request) {
|
||||
try {
|
||||
const supabase = getSupabaseServerClient();
|
||||
const { searchParams } = new URL(request.url);
|
||||
|
||||
let id = searchParams.get('id')?.trim();
|
||||
|
||||
if (!id) {
|
||||
try {
|
||||
const body = await request.json();
|
||||
id = body?.id?.trim();
|
||||
} catch {
|
||||
// Ignore JSON parse errors; query param is preferred.
|
||||
}
|
||||
}
|
||||
|
||||
if (!id) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Missing required document id' },
|
||||
{ status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const { error, count } = await supabase
|
||||
.from('mission_control_documents')
|
||||
.delete({ count: 'exact' })
|
||||
.eq('id', id);
|
||||
|
||||
if (error) {
|
||||
console.error('Supabase delete error:', error);
|
||||
return NextResponse.json({ error: error.message }, { status: 500 });
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Document not found' },
|
||||
{ status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true, id });
|
||||
} catch (err: any) {
|
||||
console.error('DELETE /api/documents error:', err);
|
||||
return NextResponse.json(
|
||||
{ error: err.message || 'Unknown error occurred' },
|
||||
{ status: 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,6 +73,26 @@ interface SearchableEntityConfig {
|
||||
getSnippet?: (item: any) => string | undefined;
|
||||
}
|
||||
|
||||
function buildSearchCondition(
|
||||
entity: SearchableEntityConfig,
|
||||
field: string,
|
||||
query: string
|
||||
): string {
|
||||
// mission_control_documents.tags is text[]; ilike fails with Postgres 42883.
|
||||
// Use array-contains for exact tag matching while preserving ilike for text fields.
|
||||
if (entity.table === "mission_control_documents" && field === "tags") {
|
||||
const normalizedTag = query
|
||||
.trim()
|
||||
.toLowerCase()
|
||||
.replace(/\\/g, "\\\\")
|
||||
.replace(/"/g, '\\"');
|
||||
|
||||
return `${field}.cs.{"${normalizedTag}"}`;
|
||||
}
|
||||
|
||||
return `${field}.ilike.%${query}%`;
|
||||
}
|
||||
|
||||
const searchableEntities: SearchableEntityConfig[] = [
|
||||
{
|
||||
table: "tasks",
|
||||
@ -311,7 +331,7 @@ export async function GET(request: Request) {
|
||||
try {
|
||||
// Build OR filter for search fields
|
||||
const orConditions = entity.searchFields
|
||||
.map(field => `${field}.ilike.%${query}%`)
|
||||
.map((field) => buildSearchCondition(entity, field, query))
|
||||
.join(",");
|
||||
|
||||
// Only select fields we need for search results
|
||||
|
||||
164
documents/ai-adoption-meta-learning-loops-plan.md
Normal file
164
documents/ai-adoption-meta-learning-loops-plan.md
Normal file
@ -0,0 +1,164 @@
|
||||
# Implementation Plan: Nine Meta-Learning Loops Integration
|
||||
|
||||
## Overview
|
||||
Integrate Vox's 9 meta-learning loops framework into Mission Control's autonomous agent system to enable closed-loop operations and progression toward full agent autonomy.
|
||||
|
||||
## Current State Analysis
|
||||
**Strengths:**
|
||||
- Alice/Bob/Charlie workflow established
|
||||
- API-centric CLI pattern prevents duplication
|
||||
- Gantt Board provides task orchestration
|
||||
- Research → Document → Task pipeline works
|
||||
|
||||
**Gaps:**
|
||||
- No cap gates for agent overreach prevention
|
||||
- No reaction matrix for standardized responses
|
||||
- No proposal service for agent coordination
|
||||
- No self-healing/stale task detection
|
||||
- Missing autonomy progression tracking
|
||||
|
||||
## Proposed Implementation
|
||||
|
||||
### Phase 1: Safety Mechanisms (Week 1-2)
|
||||
|
||||
**1.1 Cap Gates System**
|
||||
```
|
||||
Location: /lib/agents/cap-gates.ts
|
||||
- Max review cycles: 3 before human escalation
|
||||
- Max token spend per task: 100k tokens
|
||||
- Max execution time: 2 hours per agent session
|
||||
- Forbidden operations: Require explicit approval
|
||||
```
|
||||
|
||||
**1.2 Reaction Matrix**
|
||||
```
|
||||
Location: /lib/agents/reaction-matrix.ts
|
||||
Standardized responses for:
|
||||
- API failures → Retry with backoff
|
||||
- Syntax errors → Check SKILL.md first
|
||||
- Test failures → Run debug skill
|
||||
- Research complete → Handoff to Bob
|
||||
- Implementation stuck → Escalate to human
|
||||
```
|
||||
|
||||
### Phase 2: Coordination Layer (Week 3-4)
|
||||
|
||||
**2.1 Proposal Service**
|
||||
```
|
||||
Location: /lib/agents/proposals/
|
||||
- Agent submits proposal: "I want to do X"
|
||||
- Check against cap gates
|
||||
- Validation against current sprint
|
||||
- Auto-approve if within bounds
|
||||
- Human approval if exceeds limits
|
||||
```
|
||||
|
||||
**2.2 Proposal Protocol**
|
||||
```json
|
||||
{
|
||||
"proposalId": "uuid",
|
||||
"agentId": "alice-researcher",
|
||||
"type": "research|implement|test",
|
||||
"estimatedCost": "tokens",
|
||||
"estimatedTime": "minutes",
|
||||
"requiresApproval": true|false,
|
||||
"rationale": "string",
|
||||
"expectedOutput": "string"
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 3: Self-Healing (Week 5-6)
|
||||
|
||||
**3.1 Stale Task Detection**
|
||||
```
|
||||
Location: /lib/agents/health-check.ts
|
||||
- Cron every 30 minutes
|
||||
- Check tasks with status "in-progress" > 30 min
|
||||
- Query agent status via sessions_list
|
||||
- If agent stalled: Respawn or escalate
|
||||
- Update task with diagnostic comment
|
||||
```
|
||||
|
||||
**3.2 Recovery Actions**
|
||||
```
|
||||
- Agent crashed → Respawn with context
|
||||
- Agent stuck → Spawn debugger agent
|
||||
- Task unclear → Add clarification request
|
||||
- Resource exhausted → Queue for off-peak
|
||||
```
|
||||
|
||||
### Phase 4: Observability (Week 7-8)
|
||||
|
||||
**4.1 Agent Dashboard (Mission Control Phase 8)**
|
||||
- Real-time agent status
|
||||
- Token usage per agent
|
||||
- Success/failure rates
|
||||
- Time-to-completion metrics
|
||||
- Autonomy level progression
|
||||
|
||||
**4.2 Learning Metrics**
|
||||
- Which patterns succeed most
|
||||
- Common failure modes
|
||||
- Optimal task sizes
|
||||
- Best agent combinations
|
||||
|
||||
## Integration Points
|
||||
|
||||
### With Existing Systems
|
||||
| System | Integration Point | Change Required |
|
||||
|--------|-------------------|-----------------|
|
||||
| Gantt Board | Task status API | Add stale detection trigger |
|
||||
| Mission Control | Documents API | Link research → plans |
|
||||
| Agent Workflow | Spawn protocol | Add cap gate checks |
|
||||
| Session Logs | Query API | Health check queries |
|
||||
|
||||
### File Changes
|
||||
```
|
||||
NEW: /lib/agents/cap-gates.ts
|
||||
NEW: /lib/agents/reaction-matrix.ts
|
||||
NEW: /lib/agents/proposal-service.ts
|
||||
NEW: /lib/agents/health-check.ts
|
||||
NEW: /lib/agents/dashboard.ts
|
||||
MODIFY: /agents/TEAM-REGISTRY.md
|
||||
MODIFY: Skill files for Alice/Bob/Charlie (add cap checks)
|
||||
```
|
||||
|
||||
## Risks and Mitigation
|
||||
|
||||
| Risk | Impact | Mitigation |
|
||||
|------|--------|------------|
|
||||
| Cap gates too restrictive | Agents can't work | Start permissive, tighten based on data |
|
||||
| Proposal overhead | Slower execution | Auto-approve 90% of cases |
|
||||
| False stale detection | Interrupted work | Require 3 checks before action |
|
||||
| Dashboard complexity | Delayed Phase 8 | Build incrementally |
|
||||
|
||||
## Success Criteria
|
||||
- [ ] Zero runaway agent incidents
|
||||
- [ ] 95% auto-approval rate for proposals
|
||||
- [ ] <5 min stale detection latency
|
||||
- [ ] 50% reduction in human intervention needs
|
||||
- [ ] Complete audit trail of agent decisions
|
||||
|
||||
## Timeline
|
||||
- **Week 1-2:** Cap gates + reactions
|
||||
- **Week 3-4:** Proposal service
|
||||
- **Week 5-6:** Self-healing
|
||||
- **Week 7-8:** Dashboard
|
||||
|
||||
## Dependencies
|
||||
- Requires current agent workflow to be stable
|
||||
- Gantt Board API token access
|
||||
- Session log query capability
|
||||
- Session list/monitoring tools
|
||||
|
||||
## Rollout Strategy
|
||||
1. Deploy cap gates (observation mode)
|
||||
2. Enable reaction matrix
|
||||
3. Launch proposal service (with manual approval)
|
||||
4. Enable auto-approval after 1 week
|
||||
5. Add stale detection
|
||||
6. Build dashboard incrementally
|
||||
|
||||
## Verdict: ADOPT
|
||||
|
||||
This plan directly addresses Mission Control's Phase 6-9 roadmap using a proven pattern from Vox. Start with Phase 1 safety mechanisms before enabling more autonomy.
|
||||
120
documents/ai-adoption-meta-learning-loops.md
Normal file
120
documents/ai-adoption-meta-learning-loops.md
Normal file
@ -0,0 +1,120 @@
|
||||
# Nine Meta-Learning Loops: A Guide to AI Adoption in Business
|
||||
|
||||
**Source:** X Thread by [@Voxyz_ai](https://x.com/Voxyz_ai)
|
||||
**Date Researched:** Feb 25, 2026
|
||||
**Recommended Verdict:** **ADOPT** - High relevance for Mission Control's autonomous agent vision
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
Vox shares a framework of 9 meta-learning loops that enabled "AI Co-Pilot" adoption across their entire company. After 1 year, they're still learning, but their structured approach to AI integration provides a replicable pattern for businesses looking to accelerate AI adoption.
|
||||
|
||||
---
|
||||
|
||||
## The 9 Meta-Learning Loops
|
||||
|
||||
### 1. **Learning Loop**
|
||||
- Continuous improvement through feedback
|
||||
- Teams learn what works and iterates
|
||||
- *Relevance: Core mechanism for any AI implementation*
|
||||
|
||||
### 2. **Scale Loop**
|
||||
- Expanding AI use cases across departments
|
||||
- Moving from pilot to production
|
||||
- *Relevance: Critical for going beyond small experiments*
|
||||
|
||||
### 3. **Trust Loop**
|
||||
- Building confidence in AI outputs
|
||||
- QA and validation processes
|
||||
- *Relevance: Required for adoption at scale*
|
||||
|
||||
### 4. **Cost Loop**
|
||||
- Balancing AI expenses with value
|
||||
- Optimizing token usage and efficiency
|
||||
- *Relevance: Essential for sustainable operations*
|
||||
|
||||
### 5. **Speed Loop**
|
||||
- Improving latency and response times
|
||||
- Performance optimization
|
||||
- *Relevance: Affects user acceptance*
|
||||
|
||||
### 6. **Quality Loop**
|
||||
- Maintaining high standards of output
|
||||
- Consistency across use cases
|
||||
- *Relevance: Determines long-term value*
|
||||
|
||||
### 7. **Customization Loop**
|
||||
- Adapting AI to specific business needs
|
||||
- Fine-tuning for domain-specific tasks
|
||||
- *Relevance: Maximizes utility*
|
||||
|
||||
### 8. **Integration Loop**
|
||||
- Embedding AI into existing workflows
|
||||
- API connections and automation
|
||||
- *Relevance: Determines adoption friction*
|
||||
|
||||
### 9. **Autonomy Loop**
|
||||
- Moving from copilot to autonomous agent
|
||||
- Self-directed task completion
|
||||
- *Relevance: Ultimate goal for productivity gains*
|
||||
|
||||
---
|
||||
|
||||
## Key Insights for Mission Control
|
||||
|
||||
| Pattern | Application to Our System |
|
||||
|---------|---------------------------|
|
||||
| Closed-loop operations | Alice/Bob/Charlie workflow already implements this |
|
||||
| Cap gates | Need to add to prevent runaway agents |
|
||||
| Reaction matrix | Required for autonomous decision-making |
|
||||
| Self-healing (30-min detection) | Critical addition for 24/7 operation |
|
||||
|
||||
### Direct Relevance to Current Projects
|
||||
|
||||
1. **Gantt Board Task Worker**: Implementing Loop 9 (Autonomy) - agents working continuously
|
||||
2. **Subagent Orchestration**: Implements Loop 1 (Learning) and Loop 2 (Scale)
|
||||
3. **Research → Implementation Pipeline**: Maps to Loops 3-8
|
||||
|
||||
### Vox's Architecture
|
||||
- **Agent stack**: 6 autonomous agents with closed-loop operations
|
||||
- **Proposal service**: Single coordination point
|
||||
- **Human oversight**: Cap gates prevent overreach
|
||||
- **Reaction matrix**: Standardized response patterns
|
||||
|
||||
---
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
**Phase 1: Current State**
|
||||
- Alice/Bob/Charlie workflow exists
|
||||
- API-centric CLI pattern working
|
||||
- Task management through Gantt Board
|
||||
|
||||
**Phase 2: Add Loop Mechanisms**
|
||||
1. Implement cap gates (risk management)
|
||||
2. Add reaction matrix for common scenarios
|
||||
3. Build proposal service for agent coordination
|
||||
4. Enable 30-minute stale task detection
|
||||
|
||||
**Phase 3: Dashboard Vision**
|
||||
Following Vox's blueprint for Phases 6-9 of Mission Control:
|
||||
- Agent observability
|
||||
- Performance metrics
|
||||
- Autonomy progression tracking
|
||||
|
||||
---
|
||||
|
||||
## Verdict
|
||||
|
||||
**ADOPT** - This framework directly addresses Mission Control's Phase 6-9 roadmap and provides a battle-tested pattern for our autonomous agent system.
|
||||
|
||||
**Next Steps:**
|
||||
- [ ] Review implementation plan details
|
||||
- [ ] Prioritize cap gates and reaction matrix
|
||||
- [ ] Design proposal service architecture
|
||||
- [ ] Plan 30-min stale detection mechanism
|
||||
|
||||
---
|
||||
|
||||
**Tags:** #ai-adoption #automation #voxyz #mission-control #agents #meta-learning
|
||||
@ -155,9 +155,30 @@ export function useDocuments() {
|
||||
);
|
||||
|
||||
const deleteDocument = useCallback(async (id: string): Promise<boolean> => {
|
||||
// TODO: Implement via API
|
||||
console.log('Delete document not yet implemented');
|
||||
return false;
|
||||
try {
|
||||
const response = await fetchWithTimeout(`/api/documents?id=${encodeURIComponent(id)}`, {
|
||||
method: 'DELETE',
|
||||
}, 10000);
|
||||
|
||||
let result: any = null;
|
||||
try {
|
||||
result = await response.json();
|
||||
} catch {
|
||||
// Best effort parse; fall back to status text below.
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(result?.error || `HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
setDocuments((prev) => prev.filter((doc) => doc.id !== id));
|
||||
setError(null);
|
||||
return true;
|
||||
} catch (err: any) {
|
||||
console.error('[useDocuments] Delete failed:', err);
|
||||
setError(err?.message || 'Failed to delete document');
|
||||
return false;
|
||||
}
|
||||
}, []);
|
||||
|
||||
const createFolder = useCallback((name: string): Folder => {
|
||||
|
||||
@ -6,19 +6,53 @@
|
||||
set -euo pipefail
|
||||
|
||||
# Configuration
|
||||
MC_API_URL="${MC_API_URL:-http://localhost:3001/api}"
|
||||
MC_API_URL="${MC_API_URL:-https://mission-control-rho-pink.vercel.app/api}"
|
||||
MC_COOKIE_FILE="${MC_COOKIE_FILE:-$HOME/.config/mission-control/cookies.txt}"
|
||||
|
||||
# Ensure cookie directory exists
|
||||
mkdir -p "$(dirname "$MC_COOKIE_FILE")"
|
||||
|
||||
# Machine-to-machine API call (for cron/automation)
|
||||
# Uses MC_MACHINE_TOKEN env var instead of cookie auth
|
||||
# Usage: mc_api_call_machine <method> <endpoint> [data]
|
||||
mc_api_call_machine() {
|
||||
local method="$1"
|
||||
local endpoint="$2"
|
||||
local data="${3:-}"
|
||||
|
||||
local token="${MC_MACHINE_TOKEN:-}"
|
||||
if [[ -z "$token" ]]; then
|
||||
echo "Error: MC_MACHINE_TOKEN not set" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local url="${MC_API_URL}${endpoint}"
|
||||
local curl_opts=(
|
||||
-s
|
||||
-H "Content-Type: application/json"
|
||||
-H "Authorization: Bearer ${token}"
|
||||
)
|
||||
|
||||
if [[ -n "$data" ]]; then
|
||||
curl_opts+=(-d "$data")
|
||||
fi
|
||||
|
||||
curl "${curl_opts[@]}" -X "$method" "$url"
|
||||
}
|
||||
|
||||
# Make authenticated API call to Mission Control
|
||||
# Usage: mc_api_call <method> <endpoint> [data]
|
||||
mc_api_call() {
|
||||
local method="$1"
|
||||
local endpoint="$2"
|
||||
local data="${3:-}"
|
||||
|
||||
|
||||
# Machine token path for automation/cron (no cookie auth needed)
|
||||
if [[ -n "${MC_MACHINE_TOKEN:-}" ]]; then
|
||||
mc_api_call_machine "$method" "$endpoint" "$data"
|
||||
return $?
|
||||
fi
|
||||
|
||||
local url="${MC_API_URL}${endpoint}"
|
||||
local curl_opts=(
|
||||
-s
|
||||
@ -26,11 +60,11 @@ mc_api_call() {
|
||||
-c "$MC_COOKIE_FILE"
|
||||
-H "Content-Type: application/json"
|
||||
)
|
||||
|
||||
|
||||
if [[ -n "$data" ]]; then
|
||||
curl_opts+=(-d "$data")
|
||||
fi
|
||||
|
||||
|
||||
curl "${curl_opts[@]}" -X "$method" "$url"
|
||||
}
|
||||
|
||||
@ -101,6 +135,7 @@ mc_logout() {
|
||||
}
|
||||
|
||||
# Export functions for use in other scripts
|
||||
export -f mc_api_call_machine
|
||||
export -f mc_api_call
|
||||
export -f mc_get
|
||||
export -f mc_post
|
||||
|
||||
@ -147,9 +147,87 @@ handle_documents() {
|
||||
fi
|
||||
mc_get "/documents?id=$id" | jq .
|
||||
;;
|
||||
create)
|
||||
shift # Remove 'create' from args
|
||||
local title=""
|
||||
local content=""
|
||||
local folder="Research/"
|
||||
local tags='["saved", "article"]'
|
||||
local description=""
|
||||
|
||||
# Parse arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--title)
|
||||
title="$2"
|
||||
shift 2
|
||||
;;
|
||||
--content)
|
||||
content="$2"
|
||||
shift 2
|
||||
;;
|
||||
--folder)
|
||||
folder="$2"
|
||||
shift 2
|
||||
;;
|
||||
--tags)
|
||||
tags="$2"
|
||||
shift 2
|
||||
;;
|
||||
--description)
|
||||
description="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1" >&2
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Validate required fields
|
||||
if [[ -z "$title" ]]; then
|
||||
echo "Usage: ./mc.sh documents create --title <title> --content <content> [--folder <folder>] [--tags <tags>] [--description <description>]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "$content" ]]; then
|
||||
echo "Error: --content is required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get absolute path to mc.sh for API URL resolution
|
||||
local SCRIPT_DIR
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
export SCRIPT_DIR
|
||||
source "$SCRIPT_DIR/lib/api_client.sh"
|
||||
|
||||
# Build JSON payload
|
||||
local payload
|
||||
payload=$(jq -n \
|
||||
--arg title "$title" \
|
||||
--arg content "$content" \
|
||||
--arg type "markdown" \
|
||||
--arg folder "$folder" \
|
||||
--argjson tags "$tags" \
|
||||
--arg size "${#content}" \
|
||||
--arg description "${description:-Created via CLI}" \
|
||||
'{
|
||||
title: $title,
|
||||
content: $content,
|
||||
type: $type,
|
||||
folder: $folder,
|
||||
tags: $tags,
|
||||
size: ($size | tonumber),
|
||||
description: $description
|
||||
}')
|
||||
|
||||
# Create document
|
||||
mc_post "/documents" "$payload"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown documents subcommand: $subcmd" >&2
|
||||
echo "Usage: ./mc.sh documents {list|get <id>}" >&2
|
||||
echo "Usage: ./mc.sh documents {list|get <id>|create <args>}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
Loading…
Reference in New Issue
Block a user