diff --git a/modus/data-fetching.mdx b/modus/data-fetching.mdx index c715b6df..2d6c4ed2 100644 --- a/modus/data-fetching.mdx +++ b/modus/data-fetching.mdx @@ -157,9 +157,9 @@ export function getPerson(name: string): Person { const vars = new dgraph.Variables() vars.set("$name", name) - const resp = dgraph.execute( + const resp = dgraph.executeQuery( connection, - new dgraph.Request(new dgraph.Query(statement, vars)), + new dgraph.Query(statement, vars), ) const persons = JSON.parse(resp.Json).persons return persons[0] @@ -468,7 +468,7 @@ class Person { } @json class GetPersonResponse { - getPerson: Person | null + getPerson: Person | null = null } export function getPerson(name: string): Person | null { diff --git a/modus/first-modus-agent.mdx b/modus/first-modus-agent.mdx index 795f7615..126a7b07 100644 --- a/modus/first-modus-agent.mdx +++ b/modus/first-modus-agent.mdx @@ -103,104 +103,162 @@ AssemblyScript if you prefer. For AssemblyScript usage, refer to the Create a function that fetches data from an external API and uses AI for analysis: - - Create `intelligence.go`: - - ```go intelligence.go - package main - - import ( - "errors" - "fmt" - "strings" - - "github.com/hypermodeinc/modus/sdk/go/pkg/http" - "github.com/hypermodeinc/modus/sdk/go/pkg/models" - "github.com/hypermodeinc/modus/sdk/go/pkg/models/openai" - ) - - type IntelReport struct { - Quote string `json:"quote"` - Author string `json:"author"` - Analysis string `json:"analysis,omitempty"` - } + + + Create `intelligence.go`: + + ```go intelligence.go + package main - const modelName = "text-generator" + import ( + "errors" + "fmt" + "strings" - // Fetch a random quote and provide AI analysis - func GatherIntelligence() (*IntelReport, error) { - request := http.NewRequest("https://zenquotes.io/api/random") + "github.com/hypermodeinc/modus/sdk/go/pkg/http" + "github.com/hypermodeinc/modus/sdk/go/pkg/models" + "github.com/hypermodeinc/modus/sdk/go/pkg/models/openai" + ) - response, err := http.Fetch(request) - if err != nil { - return nil, err + type IntelReport struct { + Quote string `json:"q"` + Author string `json:"a"` + Analysis string `json:"analysis,omitempty"` } - if !response.Ok() { - return nil, fmt.Errorf("request failed: %d %s", response.Status, response.StatusText) + + const modelName = "text-generator" + + // Fetch a random quote and provide AI analysis + func GatherIntelligence() (*IntelReport, error) { + request := http.NewRequest("https://zenquotes.io/api/random") + + response, err := http.Fetch(request) + if err != nil { + return nil, err + } + if !response.Ok() { + return nil, fmt.Errorf("request failed: %d %s", response.Status, response.StatusText) + } + + // Parse the API response + var quotes []IntelReport + response.JSON("es) + if len(quotes) == 0 { + return nil, errors.New("no data received") + } + + // Get the quote + intel := quotes[0] + + // Generate AI analysis + analysis, err := analyzeIntelligence(intel.Quote, intel.Author) + if err != nil { + fmt.Printf("AI analysis failed for %s: %v\n", intel.Author, err) + intel.Analysis = "Analysis unavailable" + } else { + intel.Analysis = analysis + } + + return &intel, nil } - // Parse the API response - var quotes []IntelReport - response.JSON("es) - if len(quotes) == 0 { - return nil, errors.New("no data received") + // Use AI to analyze the quote + func analyzeIntelligence(quote, author string) (string, error) { + model, err := models.GetModel[openai.ChatModel](modelName) + if err != nil { + return "", err + } + + prompt := `You are an analyst. + Provide a brief insight that captures the core meaning + and practical application of this wisdom in 1-2 sentences.` + content := fmt.Sprintf("Quote: \"%s\" - %s", quote, author) + + input, err := model.CreateInput( + openai.NewSystemMessage(prompt), + openai.NewUserMessage(content), + ) + if err != nil { + return "", err + } + + input.Temperature = 0.7 + + output, err := model.Invoke(input) + if err != nil { + return "", err + } + + return strings.TrimSpace(output.Choices[0].Message.Content), nil } + ``` + + + Modify `index.ts` - // Get the quote - intel := quotes[0] + ```ts + import { http, models } from "@hypermode/modus-sdk-as"; + import { OpenAIChatModel, SystemMessage, UserMessage } from "@hypermode/modus-sdk-as/models/openai/chat"; - // Generate AI analysis - analysis, err := analyzeIntelligence(intel.Quote, intel.Author) - if err != nil { - fmt.Printf("AI analysis failed for %s: %v\n", intel.Author, err) - intel.Analysis = "Analysis unavailable" - } else { - intel.Analysis = analysis - } + export function sayHello(name: string | null = null): string { + return `Hello, ${name || "World"}!`; + } - return &intel, nil + @json + class IntelReport { + @alias("q") + quote!: string; + @alias("a") + author!: string; + analysis!: string; } - // Use AI to analyze the quote - func analyzeIntelligence(quote, author string) (string, error) { - model, err := models.GetModel[openai.ChatModel](modelName) - if err != nil { - return "", err - } + const modelName = "text-generator"; + + export function gatherIntelligence(): IntelReport { + const response = http.fetch("https://zenquotes.io/api/random"); + + if (response.status !== 200) + throw new Error("Request failed with status: " + response.status.toString() + " " + response.statusText); + + const quotes = response.json(); + + if (!quotes.length) + throw new Error("No data recieved"); + + const quote = quotes[0]; + const analysis = analyzeIntelligence(quote.quote, quote.author); + + quote.analysis = analysis; - prompt := `You are an analyst. + return quote; + } + + function analyzeIntelligence(quote: string, author: string): string { + const model = models.getModel(modelName); + + const prompt = `You are an analyst. Provide a brief insight that captures the core meaning - and practical application of this wisdom in 1-2 sentences.` - content := fmt.Sprintf("Quote: \"%s\" - %s", quote, author) + and practical application of this wisdom in 1-2 sentences.`; + const content = "Quote: " + quote + " - " + author; - input, err := model.CreateInput( - openai.NewSystemMessage(prompt), - openai.NewUserMessage(content), - ) - if err != nil { - return "", err - } + const input = model.createInput([ + new SystemMessage(prompt), + new UserMessage(content) + ]); - input.Temperature = 0.7 + input.temperature = 0.7; - output, err := model.Invoke(input) - if err != nil { - return "", err - } + const output = model.invoke(input); - return strings.TrimSpace(output.Choices[0].Message.Content), nil + return output.choices[0].message.content.trim(); } ``` - + + - Restart your development server: - - ```sh - modus dev - ``` - Modus automatically generates a GraphQL API from your functions. Since your function is named `GatherIntelligence()`, it becomes a GraphQL query field called `gatherIntelligence`. @@ -208,13 +266,13 @@ AssemblyScript if you prefer. For AssemblyScript usage, refer to the The explorer is fully GraphQL-compatible, so you can issue this query: ```graphql - query { - gatherIntelligence { - quote - author - analysis + query { + gatherIntelligence { + quote + author + analysis + } } - } ``` You'll receive a response like: diff --git a/modus/functions.mdx b/modus/functions.mdx index 8ad1e3dd..e56c1ec3 100644 --- a/modus/functions.mdx +++ b/modus/functions.mdx @@ -43,14 +43,26 @@ GraphQL API. Your functions become either **queries** (for data retrieval) or Most functions become GraphQL queries—perfect for fetching and processing data: -```go + + +```go Go // This function becomes a GraphQL query func GatherThreatIntelligence(source string) (*ThreatReport, error) { - // Data gathering and processing operation - return fetchThreatData(source) + // Data gathering and processing operation + return fetchThreatData(source) +} +``` + +```ts AssemblyScript +// This function becomes a GraphQL query +export function gatherThreatIntelligence(source: string): ThreatReport { + // Data gathering and processing operation + return fetchThreatData(source) } ``` + + Your functions are now accessible via GraphQL: ```graphql @@ -82,7 +94,9 @@ query { Functions that modify data automatically become GraphQL mutations. Modus detects these by their operation prefixes: -```go + + +```go Go // This becomes a GraphQL mutation func CreateSecurityAlert(data AlertInput) (*SecurityAlert, error) { // Create new security alert @@ -90,6 +104,16 @@ func CreateSecurityAlert(data AlertInput) (*SecurityAlert, error) { } ``` +```ts AssemblyScript +// This becomes a GraphQL mutation +export function createSecurityAlert(data: AlertInput): SecurityAlert { + // Create new security alert + return deploySecurityAlert(data) +} +``` + + + Now you can execute data modifications: ```graphql @@ -130,11 +154,14 @@ automatically become mutations. Here's a complete example that demonstrates how functions integrate external APIs with AI models for intelligent data processing: -```go + + +```go Go package main import ( "fmt" + "net/url" "strings" "github.com/hypermodeinc/modus/sdk/go/pkg/http" "github.com/hypermodeinc/modus/sdk/go/pkg/models" @@ -152,10 +179,11 @@ const modelName = "text-generator" // Function: Gather weather data and provide tactical analysis func GatherWeatherIntelligence(city string) (*WeatherIntel, error) { + city = url.QueryEscape(city) // Fetch weather data from OpenWeatherMap API url := fmt.Sprintf( - "https://api.openweathermap.org/data/2.5/weather?q=%s&appid={{API_KEY}}&units=metric", - city, + "https://api.openweathermap.org/data/2.5/weather?q=%s&units=metric", + city, ) response, err := http.Fetch(url) @@ -244,6 +272,102 @@ func analyzeTacticalConditions(city string, temp float64, conditions string) (st } ``` +```ts AssemblyScript +import { http, models } from "@hypermode/modus-sdk-as" +import { + OpenAIChatModel, + SystemMessage, + UserMessage, +} from "@hypermode/modus-sdk-as/models/openai/chat" + +@json +class WeatherIntel { + city!: string + temperature!: f64 + conditions!: string + analysis!: string +} + +@json +class WeatherData { + name!: string + main!: MainWeatherData + weather!: WeatherDescription[] +} + +@json +class MainWeatherData { + temp!: f64 +} + +@json +class WeatherDescription { + description!: string +} + +const modelName = "text-generator" + +export function gatherWeatherIntelligence(city: string): WeatherIntel { + city = encodeURIComponent(city) + const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric` + const response = http.fetch(url) + + if (!response.ok) + throw new Error( + "Weather data retrieval failed: " + + response.status.toString() + + " " + + response.statusText, + ) + + const weatherData = response.json() + + let conditions = "unknown" + + if (weatherData.weather.length) + conditions = weatherData.weather[0].description + + const analysis = analyzeTacticalConditions( + weatherData.name, + weatherData.main.temp, + conditions, + ) + + return { + city: weatherData.name, + temperature: weatherData.main.temp, + conditions, + analysis, + } +} + +function analyzeTacticalConditions( + city: string, + temperature: f64, + conditions: string, +): string { + const model = models.getModel(modelName) + + const prompt = `You are a tactical analyst evaluating weather conditions for field operations. + Provide a brief tactical assessment of how these weather conditions might impact + outdoor activities, visibility, and operational considerations in 1-2 sentences.` + + const content = `Location: ${city}, Temperatire: ${temperature}, Conditions: ${conditions}` + + const input = model.createInput([ + new SystemMessage(prompt), + new UserMessage(content), + ]) + input.temperature = 0.7 + + const output = model.invoke(input) + + return output.choices[0].message.content.trim() +} +``` + + + This function automatically becomes available as a GraphQL query: ```graphql diff --git a/modus/knowledge-graphs.mdx b/modus/knowledge-graphs.mdx index 6f6613a3..b7ac934d 100644 --- a/modus/knowledge-graphs.mdx +++ b/modus/knowledge-graphs.mdx @@ -83,71 +83,149 @@ behavior in the simulated reality. The system needs to: When new Agent activity is detected in the Matrix, you need to process it quickly. This is perfect for a stateless function: -```go + + +```go Go +package main + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/hypermodeinc/modus/sdk/go/pkg/dgraph" + "github.com/hypermodeinc/modus/sdk/go/pkg/models" + "github.com/hypermodeinc/modus/sdk/go/pkg/models/openai" +) + type AgentSighting struct { - SightingID string `json:"sighting_id"` - AgentName string `json:"agent_name"` - Location string `json:"location"` - Behavior string `json:"behavior"` - ThreatLevel int `json:"threat_level"` - Timestamp string `json:"timestamp"` -} - -func ImportAgentSighting(sighting AgentSighting) (*string, error) { - // AI-powered analysis of the Agent behavior - analysis, err := analyzeAgentWithAI(sighting.Behavior) - if err != nil { - return nil, err - } + SightingID string `json:"sighting_id"` + AgentName string `json:"agent_name"` + Location string `json:"location"` + Behavior string `json:"behavior"` + ThreatLevel int `json:"threat_level"` + Timestamp string `json:"timestamp"` + AiAnalysis *string `json:"ai_analysis,omitempty"` +} - // Store in knowledge graph - builds organizational knowledge - mutation := dgraph.NewMutation().WithSetJson(fmt.Sprintf(`{ - "dgraph.type": "AgentSighting", - "sighting_id": "%s", - "agent_name": "%s", - "location": "%s", - "behavior": "%s", - "threat_level": %d, - "timestamp": "%s", - "ai_analysis": "%s" - }`, sighting.SightingID, sighting.AgentName, sighting.Location, - sighting.Behavior, sighting.ThreatLevel, sighting.Timestamp, analysis)) - - err = dgraph.ExecuteMutations("dgraph", mutation) - if err != nil { - return nil, err - } +type ThreatAnalysisResponse struct { + SightingCount int `json:"sighting_count"` + ActiveAgents []string `json:"active_agents"` + ThreatAssessment string `json:"threat_assessment"` + Recommendations []string `json:"recommendations"` +} - result := fmt.Sprintf("Agent sighting processed: %s", sighting.SightingID) - return &result, nil +type SightingsData struct { + Sightings []AgentSighting `json:"sightings"` +} + +func ImportAgentSighting(s AgentSighting) (*string, error) { + analysis, err := analyzeAgentWithAI(s.Behavior) + if err != nil { + return nil, err + } + s.AiAnalysis = &analysis + + data, err := json.Marshal(s) + if err != nil { + return nil, err + } + + mutation := dgraph.NewMutation().WithSetJson(string(data)) + if _, err := dgraph.ExecuteMutations("dgraph", mutation); err != nil { + return nil, err + } + + res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) + return &res, nil } func analyzeAgentWithAI(behavior string) (string, error) { - model, err := models.GetModel[openai.ChatModel]("text-generator") - if err != nil { - return "", err - } + model, err := models.GetModel[openai.ChatModel]("text-generator") + if err != nil { + return "", err + } - prompt := `Analyze this Agent behavior pattern and assess threat level, - behavioral changes, and tactical implications for resistance operations.` + prompt := "Analyze this Agent behavior pattern and assess threat level, behavioral changes, and tactical implications for resistance operations. Respond with no more than 3 short sentences." + input, err := model.CreateInput( + openai.NewSystemMessage(prompt), + openai.NewUserMessage(behavior), + ) + if err != nil { + return "", err + } + input.Temperature = 0.3 - input, err := model.CreateInput( - openai.NewSystemMessage(prompt), - openai.NewUserMessage(behavior), - ) - if err != nil { - return "", err - } - input.Temperature = 0.3 + out, err := model.Invoke(input) + if err != nil { + return "", err + } + return strings.TrimSpace(out.Choices[0].Message.Content), nil +} +``` - output, err := model.Invoke(input) - if err != nil { - return "", err - } - return strings.TrimSpace(output.Choices[0].Message.Content), nil +```typescript AssemblyScript +import { Agent, agents, dgraph, models } from "@hypermode/modus-sdk-as" +import { + OpenAIChatModel, + SystemMessage, + UserMessage, +} from "@hypermode/modus-sdk-as/models/openai/chat" +import { JSON } from "json-as" + +@json +class AgentSighting { + sighting_id!: string + agent_name!: string + location!: string + behavior!: string + timestamp!: string + @omitnull() + ai_analysis: string | null = null +} + +@json +class ThreatAnalysisResponse { + sightings_count!: i32 + active_agents!: string[] + threat_assessment!: string + reccommendations!: string[] +} + +@json +class SightingsData { + sightings!: AgentSighting[] +} + +export function importAgentSighting(s: AgentSighting): string { + const analysis = analyzeAgentWithAI(s.behavior) + s.ai_analysis = analysis + + const mutation = new dgraph.Mutation(JSON.stringify(s)) + dgraph.executeMutations("dgraph", mutation) + + return "Agent sighting processed " + s.sighting_id +} + +function analyzeAgentWithAI(behavior: string): string { + const model = models.getModel("text-generator") + + const prompt = + "Analyze this Agent behavior pattern and assess threat level, behavioral changes, and tactical implications for resistance operations. Respond with no more than 3 short sentences." + + const input = model.createInput([ + new SystemMessage(prompt), + new UserMessage(behavior), + ]) + input.temperature = 0.3 + + const out = model.invoke(input) + return out.choices[0].message.content.trim() } ``` + + Now let's deploy this data import function and test it: ```graphql @@ -182,90 +260,177 @@ mutation { Now that we've got the Agent sighting data in our knowledge graph, let's analyze the broader threat landscape: -```go -type ThreatAnalysisResponse struct { - SightingCount int `json:"sighting_count"` - ActiveAgents []string `json:"active_agents"` - ThreatAssessment string `json:"threat_assessment"` - Recommendations []string `json:"recommendations"` + + +```go Go +func AnalyzeAgentPatterns(since string) (*ThreatAnalysisResponse, error) { + query := dgraph.NewQuery(` + query analyzeAgents($since: string) { + sightings(func: ge(timestamp, $since)) { + sighting_id + agent_name + location + behavior + threat_level + timestamp + ai_analysis + } + } + `).WithVariable("$since", since) + + resp, err := dgraph.ExecuteQuery("dgraph", query) + if err != nil { + return nil, err + } + + var data SightingsData + if err := json.Unmarshal([]byte(resp.Json), &data); err != nil { + return nil, err + } + + assessment, err := generateThreatAssessment(data.Sightings) + if err != nil { + return nil, err + } + + return &ThreatAnalysisResponse{ + SightingCount: len(data.Sightings), + ActiveAgents: extractActiveAgents(data.Sightings), + ThreatAssessment: assessment, + Recommendations: generateRecommendations(len(data.Sightings)), + }, nil } -func AnalyzeAgentPatterns(timeRange string) (*ThreatAnalysisResponse, error) { - // Query organizational knowledge - traverses relationships - query := dgraph.NewQuery(` - query analyzeAgents($since: string) { - sightings(func: ge(timestamp, $since)) { - agent_name - behavior - threat_level - ai_analysis - } - } - `).WithVariable("$since", timeRange) +func generateThreatAssessment(sightings []AgentSighting) (string, error) { + model, err := models.GetModel[openai.ChatModel]("text-generator") + if err != nil { + return "", err + } + + prompt := "Based on these Agent sightings, provide a strategic threat assessment focusing on behavioral patterns and risks to resistance operations. Respond with no more than 2 short sentences." + data, err := json.Marshal(sightings) + if err != nil { + return "", err + } - response, err := dgraph.ExecuteQuery("dgraph", query) - if err != nil { - return nil, err + input, err := model.CreateInput( + openai.NewSystemMessage(prompt), + openai.NewUserMessage("Agent surveillance data: "+string(data)), + ) + if err != nil { + return "", err + } + input.Temperature = 0.4 + + out, err := model.Invoke(input) + if err != nil { + return "", err + } + + return strings.TrimSpace(out.Choices[0].Message.Content), nil +} + +func extractActiveAgents(sightings []AgentSighting) []string { + seen := map[string]struct{}{} + var agents []string + for _, s := range sightings { + if _, ok := seen[s.AgentName]; !ok { + seen[s.AgentName] = struct{}{} + agents = append(agents, s.AgentName) } + } + return agents +} - // Parse and extract threat data - var data SightingsData - err = json.Unmarshal([]byte(response.Json), &data) - if err != nil { - return nil, err +func generateRecommendations(count int) []string { + switch { + case count > 5: + return []string{ + "Implement additional security measures.", + "Enhance threat detection capabilities.", + "Implement enhanced access control.", } + case count > 2: + return []string{ + "Enhance threat detection capabilities.", + "Implement enhanced access control.", + } + default: + return []string{"Implement additional security measures."} + } +} +``` - // Generate strategic assessment using AI with graph context - assessment, err := generateThreatAssessment(data.Sightings) - if err != nil { - return nil, err +```typescript AssemblyScript +export function analyzeAgentPatterns(since: string): ThreatAnalysisResponse { + const query = new dgraph.Query(` + query analyzeAgents($since: string) { + sightings(func: ge(timestamp, $since)) { + sighting_id + agent_name + location + behavior + threat_level + timestamp + ai_analysis + } } + `).withVariable("since", since) + + const resp = dgraph.executeQuery("dgraph", query) - return &ThreatAnalysisResponse{ - SightingCount: len(data.Sightings), - ActiveAgents: extractActiveAgents(data.Sightings), - ThreatAssessment: assessment, - Recommendations: generateRecommendations(len(data.Sightings)), - }, nil + const data = JSON.parse(resp.Json) + + const assessment = generateThreatAssessment(data.sightings) + + return { + sightings_count: data.sightings.length, + active_agents: extractActiveAgents(data.sightings), + threat_assessment: assessment, + reccommendations: generateRecommendations(data.sightings.length), + } } -func generateThreatAssessment(sightings interface{}) (string, error) { - model, err := models.GetModel[openai.ChatModel]("text-generator") - if err != nil { - return "", err - } +function generateThreatAssessment(sightings: AgentSighting[]): string { + const model = models.getModel("text-generator") - prompt := `Based on these Agent sightings, provide a strategic threat - assessment focusing on behavioral patterns and risks to - resistance operations.` + const prompt = + "Based on these Agent sightings, provide a strategic threat assessment focusing on behavioral patterns and risks to resistance operations. Respond with no more than 2 short sentences." - sightingsJson, err := json.Marshal(sightings) - if err != nil { - return "", err - } + const input = model.createInput([ + new SystemMessage(prompt), + new UserMessage(JSON.stringify(sightings)), + ]) + input.temperature = 0.4 - input, err := model.CreateInput( - openai.NewSystemMessage(prompt), - openai.NewUserMessage(fmt.Sprintf("Agent surveillance data: %s", - string(sightingsJson))), - ) - if err != nil { - return "", err - } - input.Temperature = 0.4 + const out = model.invoke(input) + return out.choices[0].message.content.trim() +} - output, err := model.Invoke(input) - if err != nil { - return "", err - } - return strings.TrimSpace(output.Choices[0].Message.Content), nil +function extractActiveAgents(sightings: AgentSighting[]): string[] { + return sightings.map((s) => s.agent_name) } -// Helper functions for data extraction and recommendations -func extractActiveAgents(sightings []AgentSightingData) []string { /* ... */ } -func generateRecommendations(count int) []string { /* ... */ } +function generateRecommendations(count: i32): string[] { + if (count > 5) { + return [ + "Implement additional security measures.", + "Enhance threat detection capabilities.", + "Implement enhanced access control.", + ] + } else if (count > 2) { + return [ + "Enhance threat detection capabilities.", + "Implement enhanced access control.", + ] + } else { + return ["Implement additional security measures."] + } +} ``` + + Let's query our surveillance data: ```graphql @@ -306,42 +471,46 @@ Now let's enhance our system to automatically coordinate surveillance when new data arrives. We'll deploy persistent surveillance agents and upgrade our import function to trigger them: -```go + + +```go Go +import ( + "time" + "github.com/hypermodeinc/modus/sdk/go/pkg/agents" +) + type SurveillanceAgent struct { - agents.AgentBase - MonitoredSectors []string `json:"monitored_sectors"` - SightingsTracked int `json:"sightings_tracked"` - RecentActivities []string `json:"recent_activities"` - LastSweepTime time.Time `json:"last_sweep_time"` + agents.AgentBase + MonitoredSectors []string `json:"monitored_sectors"` + SightingsTracked int `json:"sightings_tracked"` + RecentActivities []string `json:"recent_activities"` + LastSweepTime time.Time `json:"last_sweep_time"` } func (s *SurveillanceAgent) Name() string { - return "SurveillanceAgent" + return "SurveillanceAgent" } func (s *SurveillanceAgent) OnInitialize() error { - s.MonitoredSectors = []string{ - "Downtown Loop", "Megacity Financial", "Industrial District"} - s.SightingsTracked = 0 - s.RecentActivities = []string{} - s.LastSweepTime = time.Now() - return nil -} - -func (s *SurveillanceAgent) OnReceiveMessage( - msgName string, data string) (*string, error) { - switch msgName { - case "continuous_surveillance": - return s.processNewIntelligence() - case "get_status": - return s.getOperationalStatus() - } - return nil, fmt.Errorf("unrecognized directive: %s", msgName) + s.MonitoredSectors = []string{"Downtown Loop", "Megacity Financial", "Industrial District"} + s.SightingsTracked = 0 + s.RecentActivities = []string{} + s.LastSweepTime = time.Now() + return nil +} + +func (s *SurveillanceAgent) OnReceiveMessage(msgName string, data *string) (*string, error) { + switch msgName { + case "continuous_surveillance": + return s.processNewIntelligence() + case "get_status": + return s.getOperationalStatus() + } + return nil, fmt.Errorf("unrecognized directive: %s", msgName) } func (s *SurveillanceAgent) processNewIntelligence() (*string, error) { - // Query knowledge graph for latest data since last sweep - query := dgraph.NewQuery(` + query := dgraph.NewQuery(` query getRecentSightings($since: string) { sightings(func: ge(timestamp, $since)) { agent_name @@ -351,107 +520,219 @@ func (s *SurveillanceAgent) processNewIntelligence() (*string, error) { } `).WithVariable("$since", s.LastSweepTime.Format(time.RFC3339)) - _, err := dgraph.ExecuteQuery("dgraph", query) - if err != nil { - return nil, err - } - - // Update agent's surveillance state - s.LastSweepTime = time.Now() - s.SightingsTracked += 1 + _, err := dgraph.ExecuteQuery("dgraph", query) + if err != nil { + return nil, err + } - activity := fmt.Sprintf("Auto surveillance at %s", - s.LastSweepTime.Format("15:04:05")) - s.RecentActivities = append(s.RecentActivities, activity) + s.LastSweepTime = time.Now() + s.SightingsTracked++ + activity := fmt.Sprintf("Auto surveillance at %s", s.LastSweepTime.Format("15:04:05")) + s.RecentActivities = append(s.RecentActivities, activity) - // Keep only last 3 activities - if len(s.RecentActivities) > 3 { - s.RecentActivities = s.RecentActivities[1:] - } + if len(s.RecentActivities) > 3 { + s.RecentActivities = s.RecentActivities[1:] + } - result := fmt.Sprintf(`Data processed automatically. - Tracking %d sightings. Matrix integrity: COMPROMISED`, - s.SightingsTracked) - return &result, nil + result := fmt.Sprintf("Data processed automatically.\nTracking %d sightings. Matrix integrity: COMPROMISED", s.SightingsTracked) + return &result, nil } func (s *SurveillanceAgent) getOperationalStatus() (*string, error) { - status := fmt.Sprintf(`Surveillance Agent Status: + status := fmt.Sprintf(`Surveillance Agent Status: - Operational: Active - Monitoring %d sectors: %s - Last sweep: %s - Tracking %d ongoing sightings - Recent activities: %s`, - len(s.MonitoredSectors), - strings.Join(s.MonitoredSectors, ", "), - s.LastSweepTime.Format("2006-01-02 15:04:05"), - s.SightingsTracked, - strings.Join(s.RecentActivities, ", ")) - return &status, nil + len(s.MonitoredSectors), + strings.Join(s.MonitoredSectors, ", "), + s.LastSweepTime.Format("2006-01-02 15:04:05"), + s.SightingsTracked, + strings.Join(s.RecentActivities, ", "), + ) + return &status, nil } -func init() { agents.Register(&SurveillanceAgent{}) } +func (s *SurveillanceAgent) GetState() *string { return nil } +func (s *SurveillanceAgent) SetState(state *string) {} + +func init() { + agents.Register(&SurveillanceAgent{}) +} func DeploySurveillanceAgent() (string, error) { - agentInfo, err := agents.Start("SurveillanceAgent") - if err != nil { - return "", err - } - return agentInfo.Id, nil + agentInfo, err := agents.Start("SurveillanceAgent") + if err != nil { + return "", err + } + return agentInfo.Name + " - " + agentInfo.Id, nil } func GetSurveillanceStatus(agentId string) (string, error) { - result, err := agents.SendMessage(agentId, "get_status") - if err != nil { - return "", err + result, err := agents.SendMessage(agentId, "get_status") + if err != nil { + return "", err + } + if result == nil { + return "", fmt.Errorf("no response from agent") + } + return *result, nil +} +``` + +```typescript AssemblyScript +class SurveillanceAgent extends Agent { + private monitoredSectors: string[] = [] + private sightingsTracked: i32 = 0 + private recentActivities: string[] = [] + private lastSweepTime: Date = new Date(0) + + get name(): string { + return "SurveillanceAgent" + } + + onInitialize(): void { + this.monitoredSectors = [ + "Downtown Loop", + "Megacity Financial", + "Industrial District", + ] + this.lastSweepTime = new Date(Date.now()) + } + + onReceiveMessage(msgName: string, data: string | null): string { + if (msgName === "continuous_surveillance") { + return this.processNewIntelligence() + } else if (msgName === "get_status") { + return this.getOperationalStatus() } - if result == nil { - return "", fmt.Errorf("no response from agent") + throw new Error("Unrecognized directive: " + msgName) + } + + private processNewIntelligence(): string { + const query = new dgraph.Query(` + query getRecentSightings($since: string) { + sightings(func: ge(timestamp, $since)) { + agent_name + threat_level + location + } + } + `).withVariable("since", this.lastSweepTime.toISOString()) + + dgraph.executeQuery("dgraph", query) + + this.lastSweepTime = new Date(Date.now()) + this.sightingsTracked++ + + const activity = "Auto surveillance at " + this.lastSweepTime.toTimeString() + this.recentActivities.push(activity) + + if (this.recentActivities.length > 3) { + this.recentActivities.shift() } - return *result, nil + + return `Data processed automatically.\nTracking ${this.sightingsTracked} sightings. Matrix integrity: COMPROMISED` + } + + private getOperationalStatus(): string { + return `Surveillance Agent Status: +- Operational: Active +- Monitoring ${this.monitoredSectors.length.toString()} sectors: ${this.monitoredSectors.join(", ")} +- Last sweep: ${this.lastSweepTime.toISOString().replace("T", " ").slice(0, 19)} +- Tracking ${this.sightingsTracked.toString()} ongoing sightings +- Recent activities: ${this.recentActivities.join(", ")}` + } + + getState(): string { + return "" + // return JSON.stringify(this); + } + + setState(data: string | null): void { + // if (!data) return; + // const state = JSON.parse(data); + // this.monitoredSectors = state.monitoredSectors; + // this.sightingsTracked = state.sightingsTracked; + // this.recentActivities = state.recentActivities; + // this.lastSweepTime = state.lastSweepTime; + } +} + +agents.register() + +export function deploySurveillanceAgent(): string { + const agentInfo = agents.start("SurveillanceAgent") + return `${agentInfo.name} - ${agentInfo.id}` +} + +export function getSurveillanceStatus(agentId: string): string { + const result = agents.sendMessage(agentId, "get_status") + if (result == null) { + throw new Error("No response from agent") + } + return result } ``` + + Now let's enhance our original import function to automatically trigger surveillance: -```go -func ImportAgentSighting(sighting AgentSighting) (*string, error) { - // AI-powered analysis of the Agent behavior - analysis, err := analyzeAgentWithAI(sighting.Behavior) - if err != nil { - return nil, err - } + - // Store in knowledge graph - builds organizational knowledge - mutation := dgraph.NewMutation().WithSetJson(fmt.Sprintf(`{ - "dgraph.type": "AgentSighting", - "sighting_id": "%s", - "agent_name": "%s", - "location": "%s", - "behavior": "%s", - "threat_level": %d, - "timestamp": "%s", - "ai_analysis": "%s" - }`, sighting.SightingID, sighting.AgentName, sighting.Location, - sighting.Behavior, sighting.ThreatLevel, sighting.Timestamp, analysis)) - - err = dgraph.ExecuteMutations("dgraph", mutation) - if err != nil { - return nil, err - } +```go Go +func ImportAgentSighting(s AgentSighting, surveillanceAgentId *string) (*string, error) { + analysis, err := analyzeAgentWithAI(s.Behavior) + if err != nil { + return nil, err + } + s.AiAnalysis = &analysis + + data, err := json.Marshal(s) + if err != nil { + return nil, err + } + + mutation := dgraph.NewMutation().WithSetJson(string(data)) + if _, err := dgraph.ExecuteMutations("dgraph", mutation); err != nil { + return nil, err + } - // Automatically trigger surveillance via async message - err = agents.SendMessageAsync("agent_neo_001", "continuous_surveillance") - if err != nil { - return nil, err + if surveillanceAgentId != nil { + if err := agents.SendMessageAsync(*surveillanceAgentId, "continuous_surveillance"); err != nil { + return nil, err } + } - result := fmt.Sprintf("Agent sighting processed: %s", sighting.SightingID) - return &result, nil + res := fmt.Sprintf("Agent sighting processed: %s", s.SightingID) + return &res, nil } ``` +```typescript AssemblyScript +export function importAgentSighting( + s: AgentSighting, + surveilanceAgentId: string | null = null, +): string { + const analysis = analyzeAgentWithAI(s.behavior) + s.ai_analysis = analysis + + const mutation = new dgraph.Mutation(JSON.stringify(s)) + dgraph.executeMutations("dgraph", mutation) + + if (surveilanceAgentId) { + agents.sendMessageAsync(surveilanceAgentId, "continuous_surveillance") + } + + return "Agent sighting processed " + s.sighting_id +} +``` + + + Deploy your surveillance agent: ```graphql @@ -507,7 +788,7 @@ messaging. Check the surveillance status: ```graphql query { - getSurveillanceStatus(agentId: "agent_neo_001") + surveillanceStatus(agentId: "agent_neo_001") } ``` @@ -516,14 +797,15 @@ query { ```json { "data": { - "getSurveillanceStatus": "Surveillance Agent Status: - - Operational: Active - - Monitoring 3 sectors: Downtown Loop, - Megacity Financial, Industrial District - - Last sweep: 2025-01-15 15:45:22 - - Tracking 2 ongoing sightings - - Recent activities: Auto surveillance at 14:30:05, - Auto surveillance at 15:45:22" + "surveillanceStatus": + "Surveillance Agent Status: + - Operational: Active + - Monitoring 3 sectors: Downtown Loop, + Megacity Financial, Industrial District + - Last sweep: 2025-01-15 15:45:22 + - Tracking 2 ongoing sightings + - Recent activities: Auto surveillance at 14:30:05, + Auto surveillance at 15:45:22" } } ``` @@ -552,12 +834,13 @@ query { "analyzeAgentPatterns": { "sightingCount": 2, "activeAgents": ["Smith", "Brown"], - "threatAssessment": "Critical escalation detected. Agent Smith's - enhanced replication capabilities combined with - Agent Brown's encryption countermeasures indicates - coordinated Matrix defense upgrade. Systematic - pattern suggests machines adapting to resistance - operations.", + "threatAssessment": + "Critical escalation detected. Agent Smith's + enhanced replication capabilities combined with + Agent Brown's encryption countermeasures indicates + coordinated Matrix defense upgrade. Systematic + pattern suggests machines adapting to resistance + operations.", "recommendations": [ "Emergency extraction protocols", "Activate deep cover cells", diff --git a/modus/model-invoking.mdx b/modus/model-invoking.mdx index aafba0fe..0b67f0a1 100644 --- a/modus/model-invoking.mdx +++ b/modus/model-invoking.mdx @@ -159,7 +159,6 @@ func GenerateText(instruction, prompt string) (string, error) { import { models } from "@hypermode/modus-sdk-as" import { OpenAIChatModel, - ResponseFormat, SystemMessage, UserMessage, } from "@hypermode/modus-sdk-as/models/openai/chat" @@ -225,12 +224,8 @@ func ClassifyText(text string, threshold float32) (string, error) { ```ts AssemblyScript import { models } from "@hypermode/modus-sdk-as" -import { - ClassificationModel, - ClassifierResult, -} from "@hypermode/modus-sdk-as/models/experimental/classification" +import { ClassificationModel } from "@hypermode/modus-sdk-as/models/experimental/classification" -// this model name should match the one defined in the modus.json manifest file const modelName: string = "my-classifier" // this function takes input text and a probability threshold, and returns the @@ -241,12 +236,14 @@ export function classifyText(text: string, threshold: f32): string { const input = model.createInput([text]) const output = model.invoke(input) - const prediction = output.predictions[0] - if (prediction.confidence >= threshold) { - return prediction.label + const predictions = output.predictions + + const prediction = predictions[0] + if (prediction.confidence < threshold) { + return "" } - return "" + return prediction.label } ```