← back to julianshen__rubichan

Function bodies 513 total

All specs Real LLM only Function bodies
goplugin.pluginContext.GitDiff method · go · L447-L455 (9 LOC)
internal/skills/goplugin/goplugin.go
func (c *pluginContext) GitDiff(args ...string) (string, error) {
	if err := c.checker.CheckPermission(skills.PermGitRead); err != nil {
		return "", fmt.Errorf("GitDiff: %w", err)
	}
	if c.gitRunner == nil {
		return "", fmt.Errorf("GitDiff: git runner not configured")
	}
	return c.gitRunner.Diff(args...)
}
goplugin.pluginContext.GitLog method · go · L458-L466 (9 LOC)
internal/skills/goplugin/goplugin.go
func (c *pluginContext) GitLog(args ...string) ([]skillsdk.GitCommit, error) {
	if err := c.checker.CheckPermission(skills.PermGitRead); err != nil {
		return nil, fmt.Errorf("GitLog: %w", err)
	}
	if c.gitRunner == nil {
		return nil, fmt.Errorf("GitLog: git runner not configured")
	}
	return c.gitRunner.Log(args...)
}
goplugin.pluginContext.GitStatus method · go · L469-L477 (9 LOC)
internal/skills/goplugin/goplugin.go
func (c *pluginContext) GitStatus() ([]skillsdk.GitFileStatus, error) {
	if err := c.checker.CheckPermission(skills.PermGitRead); err != nil {
		return nil, fmt.Errorf("GitStatus: %w", err)
	}
	if c.gitRunner == nil {
		return nil, fmt.Errorf("GitStatus: git runner not configured")
	}
	return c.gitRunner.Status()
}
goplugin.pluginContext.GetEnv method · go · L480-L485 (6 LOC)
internal/skills/goplugin/goplugin.go
func (c *pluginContext) GetEnv(key string) string {
	if err := c.checker.CheckPermission(skills.PermEnvRead); err != nil {
		return ""
	}
	return os.Getenv(key)
}
goplugin.pluginContext.InvokeSkill method · go · L493-L501 (9 LOC)
internal/skills/goplugin/goplugin.go
func (c *pluginContext) InvokeSkill(name string, input map[string]any) (map[string]any, error) {
	if err := c.checker.CheckPermission(skills.PermSkillInvoke); err != nil {
		return nil, fmt.Errorf("InvokeSkill: %w", err)
	}
	if c.skillInvoker == nil {
		return nil, fmt.Errorf("InvokeSkill: skill invoker not configured")
	}
	return c.skillInvoker.Invoke(name, input)
}
main.testPlugin.Manifest method · go · L15-L23 (9 LOC)
internal/skills/goplugin/testdata/testplugin.go
func (p *testPlugin) Manifest() skillsdk.Manifest {
	return skillsdk.Manifest{
		Name:        "test-plugin",
		Version:     "1.0.0",
		Description: "A test plugin",
		Author:      "test",
		License:     "MIT",
	}
}
skills.LifecycleManager.Register method · go · L57-L66 (10 LOC)
internal/skills/hooks.go
func (lm *LifecycleManager) Register(phase HookPhase, skillName string, priority int, handler HookHandler) {
	lm.mu.Lock()
	defer lm.mu.Unlock()

	lm.handlers[phase] = append(lm.handlers[phase], skillHookEntry{
		skillName: skillName,
		priority:  priority,
		handler:   handler,
	})
}
Source: Repobility analyzer · https://repobility.com
skills.LifecycleManager.Unregister method · go · L69-L86 (18 LOC)
internal/skills/hooks.go
func (lm *LifecycleManager) Unregister(skillName string) {
	lm.mu.Lock()
	defer lm.mu.Unlock()

	for phase, entries := range lm.handlers {
		filtered := entries[:0]
		for _, e := range entries {
			if e.skillName != skillName {
				filtered = append(filtered, e)
			}
		}
		if len(filtered) == 0 {
			delete(lm.handlers, phase)
		} else {
			lm.handlers[phase] = filtered
		}
	}
}
skills.LifecycleManager.Dispatch method · go · L100-L148 (49 LOC)
internal/skills/hooks.go
func (lm *LifecycleManager) Dispatch(event HookEvent) (*HookResult, error) {
	// Snapshot handlers under read lock, then release before calling them.
	lm.mu.RLock()
	entries, ok := lm.handlers[event.Phase]
	if !ok || len(entries) == 0 {
		lm.mu.RUnlock()
		return nil, nil
	}
	sorted := make([]skillHookEntry, len(entries))
	copy(sorted, entries)
	lm.mu.RUnlock()

	// Sort by priority (stable sort preserves registration order for equal priorities).
	sort.SliceStable(sorted, func(i, j int) bool {
		return sorted[i].priority < sorted[j].priority
	})

	isCancellable := cancellablePhases[event.Phase]
	isModifying := modifyingPhases[event.Phase]

	var lastResult *HookResult

	for _, entry := range sorted {
		result, err := entry.handler(event)
		if err != nil {
			return nil, fmt.Errorf("hook handler %q (phase %s) failed: %w",
				entry.skillName, event.Phase, err)
		}

		lastResult = &result

		// For cancellable phases, stop on first cancellation.
		if isCancellable && result.Cancel {
			re
skills.SecurityRuleAdapter.RegisterScanner method · go · L43-L51 (9 LOC)
internal/skills/integration.go
func (a *SecurityRuleAdapter) RegisterScanner(skillName, scannerName string, fn ScannerFunc) {
	a.mu.Lock()
	defer a.mu.Unlock()
	a.scanners = append(a.scanners, RegisteredScanner{
		SkillName: skillName,
		Name:      scannerName,
		Scan:      fn,
	})
}
skills.SecurityRuleAdapter.Scanners method · go · L54-L60 (7 LOC)
internal/skills/integration.go
func (a *SecurityRuleAdapter) Scanners() []RegisteredScanner {
	a.mu.RLock()
	defer a.mu.RUnlock()
	result := make([]RegisteredScanner, len(a.scanners))
	copy(result, a.scanners)
	return result
}
skills.SecurityRuleAdapter.UnregisterBySkill method · go · L63-L73 (11 LOC)
internal/skills/integration.go
func (a *SecurityRuleAdapter) UnregisterBySkill(skillName string) {
	a.mu.Lock()
	defer a.mu.Unlock()
	var filtered []RegisteredScanner
	for _, s := range a.scanners {
		if s.SkillName != skillName {
			filtered = append(filtered, s)
		}
	}
	a.scanners = filtered
}
skills.PromptCollector.Fragments method · go · L104-L110 (7 LOC)
internal/skills/integration.go
func (pc *PromptCollector) Fragments() []PromptFragment {
	pc.mu.RLock()
	defer pc.mu.RUnlock()
	result := make([]PromptFragment, len(pc.fragments))
	copy(result, pc.fragments)
	return result
}
skills.PromptCollector.RemoveBySkill method · go · L113-L123 (11 LOC)
internal/skills/integration.go
func (pc *PromptCollector) RemoveBySkill(skillName string) {
	pc.mu.Lock()
	defer pc.mu.Unlock()
	var filtered []PromptFragment
	for _, f := range pc.fragments {
		if f.SkillName != skillName {
			filtered = append(filtered, f)
		}
	}
	pc.fragments = filtered
}
skills.WorkflowRunner.Invoke method · go · L151-L159 (9 LOC)
internal/skills/integration.go
func (wr *WorkflowRunner) Invoke(ctx context.Context, name string, args map[string]any) (map[string]any, error) {
	wr.mu.RLock()
	handler, ok := wr.workflows[name]
	wr.mu.RUnlock()
	if !ok {
		return nil, fmt.Errorf("workflow %q not found", name)
	}
	return handler(ctx, args)
}
Repobility · code-quality intelligence · https://repobility.com
skills.wirePromptSkill function · go · L172-L211 (40 LOC)
internal/skills/integration.go
func wirePromptSkill(rt *Runtime, sk *Skill) {
	fragment := PromptFragment{
		SkillName:        sk.Manifest.Name,
		SystemPromptFile: sk.Manifest.Prompt.SystemPromptFile,
		ContextFiles:     sk.Manifest.Prompt.ContextFiles,
		MaxContextTokens: sk.Manifest.Prompt.MaxContextTokens,
	}

	// Read the system prompt file content if a file path is specified and the
	// skill has a directory on disk. For built-in skills (Dir=""), the
	// SystemPromptFile value is used as inline content.
	if sk.Manifest.Prompt.SystemPromptFile != "" {
		if sk.Dir != "" {
			promptPath := filepath.Join(sk.Dir, sk.Manifest.Prompt.SystemPromptFile)
			data, err := os.ReadFile(promptPath)
			if err != nil {
				fragment.ResolvedPrompt = fmt.Sprintf("[error reading prompt file %q: %s]", promptPath, err)
			} else {
				fragment.ResolvedPrompt = string(data)
			}
		} else {
			// Built-in skills without a directory use SystemPromptFile as
			// inline content (no file to read).
			fragment.ResolvedPrompt = sk.Manifes
skills.wireSecurityRuleSkill function · go · L214-L219 (6 LOC)
internal/skills/integration.go
func wireSecurityRuleSkill(rt *Runtime, sk *Skill) {
	// The actual scanner functions are registered externally via
	// rt.securityAdapter.RegisterScanner(). Here we just ensure the skill
	// type is acknowledged during activation. Scanners may be pre-registered
	// by the backend or by the caller before activation.
}
skills.NewLoader function · go · L46-L52 (7 LOC)
internal/skills/loader.go
func NewLoader(userDir, projectDir string) *Loader {
	return &Loader{
		userDir:    userDir,
		projectDir: projectDir,
		builtins:   make(map[string]*SkillManifest),
	}
}
skills.Loader.Discover method · go · L74-L189 (116 LOC)
internal/skills/loader.go
func (l *Loader) Discover(explicit []string) ([]DiscoveredSkill, []string, error) {
	explicitSet := make(map[string]bool, len(explicit))
	for _, name := range explicit {
		explicitSet[name] = true
	}

	// Collect skills from all directory sources.
	// We build a map keyed by skill name; higher-priority sources overwrite lower ones.
	byName := make(map[string]DiscoveredSkill)

	// 1. Project skills (lowest directory priority).
	projectSkills, err := scanDir(l.projectDir, SourceProject)
	if err != nil {
		return nil, nil, err
	}
	for _, ds := range projectSkills {
		byName[ds.Manifest.Name] = ds
	}

	// 2. User skills override project skills.
	userSkills, err := scanDir(l.userDir, SourceUser)
	if err != nil {
		return nil, nil, err
	}
	for _, ds := range userSkills {
		byName[ds.Manifest.Name] = ds
	}

	// 3. Built-in skills override everything from directories.
	for name, m := range l.builtins {
		byName[name] = DiscoveredSkill{
			Manifest: m,
			Dir:      "",
			Source:   SourceBuilti
skills.scanDir function · go · L193-L230 (38 LOC)
internal/skills/loader.go
func scanDir(dir string, source Source) ([]DiscoveredSkill, error) {
	entries, err := os.ReadDir(dir)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, fmt.Errorf("scan skills dir %q: %w", dir, err)
	}

	var results []DiscoveredSkill
	for _, entry := range entries {
		if !entry.IsDir() {
			continue
		}

		yamlPath := filepath.Join(dir, entry.Name(), "SKILL.yaml")
		data, err := os.ReadFile(yamlPath)
		if err != nil {
			if os.IsNotExist(err) {
				continue
			}
			return nil, fmt.Errorf("read skill manifest %q: %w", yamlPath, err)
		}

		manifest, err := ParseManifest(data)
		if err != nil {
			return nil, fmt.Errorf("parse skill %q: %w", entry.Name(), err)
		}

		results = append(results, DiscoveredSkill{
			Manifest: manifest,
			Dir:      filepath.Join(dir, entry.Name()),
			Source:   source,
		})
	}

	return results, nil
}
skills.ParseManifest function · go · L181-L192 (12 LOC)
internal/skills/manifest.go
func ParseManifest(data []byte) (*SkillManifest, error) {
	var m SkillManifest
	if err := yaml.Unmarshal(data, &m); err != nil {
		return nil, fmt.Errorf("parse manifest: %w", err)
	}

	if err := validateManifest(&m); err != nil {
		return nil, err
	}

	return &m, nil
}
skills.validateManifest function · go · L194-L259 (66 LOC)
internal/skills/manifest.go
func validateManifest(m *SkillManifest) error {
	// Required fields.
	if m.Name == "" {
		return fmt.Errorf("manifest validation: name is required")
	}
	if m.Version == "" {
		return fmt.Errorf("manifest validation: version is required")
	}
	if m.Description == "" {
		return fmt.Errorf("manifest validation: description is required")
	}
	if len(m.Types) == 0 {
		return fmt.Errorf("manifest validation: types is required (at least one skill type)")
	}

	// Name format and length.
	const maxNameLength = 128
	if len(m.Name) > maxNameLength {
		return fmt.Errorf("manifest validation: name exceeds maximum length (%d > %d)", len(m.Name), maxNameLength)
	}
	if !nameRegex.MatchString(m.Name) {
		return fmt.Errorf("manifest validation: invalid name %q (must match %s)", m.Name, nameRegex.String())
	}

	// Skill types.
	for _, st := range m.Types {
		if !validSkillTypes[st] {
			return fmt.Errorf("manifest validation: unknown skill type %q", st)
		}
	}

	// Permissions.
	for _, p := range m.Permiss
mcpbackend.NewMCPBackend function · go · L27-L32 (6 LOC)
internal/skills/mcpbackend/backend.go
func NewMCPBackend(serverName string, transport mcpclient.Transport) *MCPBackend {
	return &MCPBackend{
		serverName: serverName,
		transport:  transport,
	}
}
Repobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
mcpbackend.NewMCPBackendFromConfig function · go · L37-L68 (32 LOC)
internal/skills/mcpbackend/backend.go
func NewMCPBackendFromConfig(ctx context.Context, serverName, transport, command string, args []string, sseURL string) (*MCPBackend, error) {
	var t mcpclient.Transport
	var err error

	switch transport {
	case "stdio":
		if command == "" {
			return nil, fmt.Errorf("mcp backend: stdio transport requires a command")
		}
		t, err = mcpclient.NewStdioTransport(command, args)
		if err != nil {
			return nil, fmt.Errorf("mcp backend: create stdio transport: %w", err)
		}
	case "sse":
		if sseURL == "" {
			return nil, fmt.Errorf("mcp backend: sse transport requires a url")
		}
		initCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
		defer cancel()
		t, err = mcpclient.NewSSETransport(initCtx, sseURL)
		if err != nil {
			return nil, fmt.Errorf("mcp backend: create sse transport: %w", err)
		}
	default:
		return nil, fmt.Errorf("mcp backend: unsupported transport %q", transport)
	}

	return &MCPBackend{
		serverName: serverName,
		transport:  t,
	}, nil
}
mcpbackend.MCPBackend.LoadWithContext method · go · L72-L90 (19 LOC)
internal/skills/mcpbackend/backend.go
func (b *MCPBackend) LoadWithContext(ctx context.Context) error {
	b.client = mcpclient.NewClient(b.serverName, b.transport)

	if err := b.client.Initialize(ctx); err != nil {
		return fmt.Errorf("initialize MCP server %q: %w", b.serverName, err)
	}

	mcpTools, err := b.client.ListTools(ctx)
	if err != nil {
		return fmt.Errorf("list MCP tools from %q: %w", b.serverName, err)
	}

	b.tools = make([]tools.Tool, len(mcpTools))
	for i, mt := range mcpTools {
		b.tools[i] = mcpclient.WrapTool(b.serverName, b.client, mt)
	}

	return nil
}
mcpbackend.MCPBackend.Unload method · go · L109-L115 (7 LOC)
internal/skills/mcpbackend/backend.go
func (b *MCPBackend) Unload() error {
	b.tools = nil
	if b.client != nil {
		return b.client.Close()
	}
	return nil
}
process.NewProcessBackend function · go · L79-L88 (10 LOC)
internal/skills/process/manager.go
func NewProcessBackend(opts ...Option) *ProcessBackend {
	b := &ProcessBackend{
		callTimeout:     defaultCallTimeout,
		registeredHooks: make(map[skills.HookPhase]skills.HookHandler),
	}
	for _, opt := range opts {
		opt(b)
	}
	return b
}
process.ProcessBackend.Load method · go · L92-L122 (31 LOC)
internal/skills/process/manager.go
func (b *ProcessBackend) Load(manifest skills.SkillManifest, checker skills.PermissionChecker) error {
	if manifest.Implementation.Entrypoint == "" {
		return fmt.Errorf("load process: entrypoint is required")
	}

	// Validate entrypoint is an absolute path to prevent executing arbitrary binaries.
	if !filepath.IsAbs(manifest.Implementation.Entrypoint) {
		return fmt.Errorf("load process: entrypoint must be an absolute path, got %q", manifest.Implementation.Entrypoint)
	}

	b.manifest = manifest
	b.checker = checker
	b.stopped = false
	b.stopCh = make(chan struct{})

	if err := b.startProcess(); err != nil {
		return err
	}

	if err := b.initialize(); err != nil {
		b.mu.Lock()
		b.killAndCleanupLocked()
		b.mu.Unlock()
		return fmt.Errorf("load process %q: initialize failed: %w", manifest.Name, err)
	}

	// Start crash monitor goroutine with initial generation.
	go b.monitorProcess(b.generation)

	return nil
}
process.ProcessBackend.Tools method · go · L126-L135 (10 LOC)
internal/skills/process/manager.go
func (b *ProcessBackend) Tools() []tools.Tool {
	b.mu.Lock()
	defer b.mu.Unlock()

	result := make([]tools.Tool, len(b.registeredTools))
	for i := range b.registeredTools {
		result[i] = &b.registeredTools[i]
	}
	return result
}
process.ProcessBackend.Hooks method · go · L139-L148 (10 LOC)
internal/skills/process/manager.go
func (b *ProcessBackend) Hooks() map[skills.HookPhase]skills.HookHandler {
	b.mu.Lock()
	defer b.mu.Unlock()

	result := make(map[skills.HookPhase]skills.HookHandler, len(b.registeredHooks))
	for k, v := range b.registeredHooks {
		result[k] = v
	}
	return result
}
process.ProcessBackend.Unload method · go · L152-L176 (25 LOC)
internal/skills/process/manager.go
func (b *ProcessBackend) Unload() error {
	b.mu.Lock()
	defer b.mu.Unlock()

	if b.cmd == nil {
		return nil
	}

	b.stopped = true

	// Signal the crash monitor to stop.
	close(b.stopCh)

	// Try to send shutdown gracefully.
	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
	defer cancel()
	b.callLocked(ctx, "shutdown", nil) //nolint: errcheck // best effort

	b.killAndCleanupLocked()

	b.registeredTools = nil
	b.registeredHooks = make(map[skills.HookPhase]skills.HookHandler)

	return nil
}
Repobility · severity-and-effort ranking · https://repobility.com
process.ProcessBackend.call method · go · L180-L185 (6 LOC)
internal/skills/process/manager.go
func (b *ProcessBackend) call(ctx context.Context, method string, params any) (*JSONRPCResponse, error) {
	b.mu.Lock()
	defer b.mu.Unlock()

	return b.callLocked(ctx, method, params)
}
process.ProcessBackend.callLocked method · go · L189-L241 (53 LOC)
internal/skills/process/manager.go
func (b *ProcessBackend) callLocked(ctx context.Context, method string, params any) (*JSONRPCResponse, error) {
	if b.cmd == nil {
		return nil, fmt.Errorf("process not running")
	}

	id := int(b.nextID.Add(1))

	req, err := NewRequest(id, method, params)
	if err != nil {
		return nil, fmt.Errorf("create request: %w", err)
	}

	data, err := json.Marshal(req)
	if err != nil {
		return nil, fmt.Errorf("marshal request: %w", err)
	}

	// Write request to stdin.
	if _, err := fmt.Fprintf(b.stdin, "%s\n", data); err != nil {
		return nil, fmt.Errorf("write to process stdin: %w", err)
	}

	// Apply call timeout.
	deadline := b.callTimeout
	if d, ok := ctx.Deadline(); ok {
		remaining := time.Until(d)
		if remaining < deadline {
			deadline = remaining
		}
	}

	// Read response from the dedicated reader goroutine's channel.
	select {
	case sr := <-b.readCh:
		if !sr.ok {
			return nil, fmt.Errorf("process closed stdout")
		}

		resp, err := DecodeResponse([]byte(sr.line))
		if err != nil {
		
process.ProcessBackend.startProcess method · go · L246-L279 (34 LOC)
internal/skills/process/manager.go
func (b *ProcessBackend) startProcess() error {
	cmd := exec.Command(b.manifest.Implementation.Entrypoint)

	stdin, err := cmd.StdinPipe()
	if err != nil {
		return fmt.Errorf("start process: pipe setup: %w", err)
	}

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		return fmt.Errorf("start process: pipe setup: %w", err)
	}

	if err := cmd.Start(); err != nil {
		return fmt.Errorf("start process %q: %w", b.manifest.Implementation.Entrypoint, err)
	}

	b.cmd = cmd
	b.stdin = stdin
	b.readCh = make(chan readResult, 1)

	// Dedicated reader goroutine — owns the scanner and terminates when
	// stdout is closed (process killed or exited).
	go func(ch chan<- readResult) {
		scanner := bufio.NewScanner(stdout)
		scanner.Buffer(make([]byte, 1024*1024), 1024*1024)
		for scanner.Scan() {
			ch <- readResult{line: scanner.Text(), ok: true}
		}
		ch <- readResult{ok: false}
	}(b.readCh)

	return nil
}
process.ProcessBackend.initialize method · go · L282-L335 (54 LOC)
internal/skills/process/manager.go
func (b *ProcessBackend) initialize() error {
	manifestData := map[string]any{
		"name":    b.manifest.Name,
		"version": b.manifest.Version,
	}

	ctx, cancel := context.WithTimeout(context.Background(), b.callTimeout)
	defer cancel()

	resp, err := b.callLocked(ctx, "initialize", manifestData)
	if err != nil {
		return err
	}

	// Parse initialize result for tools and hooks.
	var initResult struct {
		Tools []struct {
			Name        string          `json:"name"`
			Description string          `json:"description"`
			InputSchema json.RawMessage `json:"input_schema"`
		} `json:"tools"`
		Hooks []string `json:"hooks"`
	}
	if err := json.Unmarshal(resp.Result, &initResult); err != nil {
		return fmt.Errorf("parse initialize result: %w", err)
	}

	// Register tools.
	b.registeredTools = make([]processTool, len(initResult.Tools))
	for i, td := range initResult.Tools {
		b.registeredTools[i] = processTool{
			name:        td.Name,
			description: td.Description,
			inputSchema: td.InputSchem
process.ProcessBackend.handleHook method · go · L338-L364 (27 LOC)
internal/skills/process/manager.go
func (b *ProcessBackend) handleHook(event skills.HookEvent, phase skills.HookPhase) (skills.HookResult, error) {
	ctx := event.Ctx
	if ctx == nil {
		ctx = context.Background()
	}

	resp, err := b.call(ctx, "hook/handle", map[string]any{
		"phase": phase.String(),
		"data":  event.Data,
	})
	if err != nil {
		return skills.HookResult{}, fmt.Errorf("hook/handle: %w", err)
	}

	var hookResp struct {
		Modified map[string]any `json:"modified"`
		Cancel   bool           `json:"cancel"`
	}
	if err := json.Unmarshal(resp.Result, &hookResp); err != nil {
		return skills.HookResult{}, fmt.Errorf("parse hook result: %w", err)
	}

	return skills.HookResult{
		Modified: hookResp.Modified,
		Cancel:   hookResp.Cancel,
	}, nil
}
process.ProcessBackend.monitorProcess method · go · L369-L398 (30 LOC)
internal/skills/process/manager.go
func (b *ProcessBackend) monitorProcess(gen int64) {
	b.mu.Lock()
	cmd := b.cmd
	b.mu.Unlock()

	if cmd == nil || cmd.Process == nil {
		return
	}

	// Wait for the process to exit (does not need the lock — we captured cmd).
	cmd.Wait() //nolint: errcheck

	// Check if we were intentionally stopped.
	select {
	case <-b.stopCh:
		return
	default:
	}

	// Verify we are still the active monitor (generation hasn't changed).
	b.mu.Lock()
	if b.generation != gen || b.stopped {
		b.mu.Unlock()
		return
	}
	b.mu.Unlock()

	// Process crashed unexpectedly -- restart with backoff.
	b.restart(gen)
}
process.ProcessBackend.restart method · go · L401-L446 (46 LOC)
internal/skills/process/manager.go
func (b *ProcessBackend) restart(gen int64) {
	backoff := 50 * time.Millisecond
	maxBackoff := 5 * time.Second
	maxAttempts := 5

	for i := 0; i < maxAttempts; i++ {
		select {
		case <-b.stopCh:
			return
		case <-time.After(backoff):
		}

		b.mu.Lock()
		if b.stopped || b.generation != gen {
			b.mu.Unlock()
			return
		}

		// Clean up old process state.
		b.cmd = nil
		b.stdin = nil
		b.readCh = nil

		if err := b.startProcess(); err != nil {
			b.mu.Unlock()
			backoff = min(backoff*2, maxBackoff)
			continue
		}

		if err := b.initialize(); err != nil {
			b.killAndCleanupLocked()
			b.mu.Unlock()
			backoff = min(backoff*2, maxBackoff)
			continue
		}

		// Bump generation so the old monitor cannot race.
		b.generation++
		newGen := b.generation
		b.mu.Unlock()

		// Successfully restarted. Start monitoring again with new generation.
		go b.monitorProcess(newGen)
		return
	}
}
process.ProcessBackend.killProcess method · go · L449-L456 (8 LOC)
internal/skills/process/manager.go
func (b *ProcessBackend) killProcess() {
	b.mu.Lock()
	defer b.mu.Unlock()

	if b.cmd != nil && b.cmd.Process != nil {
		b.cmd.Process.Kill() //nolint: errcheck
	}
}
Source: Repobility analyzer · https://repobility.com
process.ProcessBackend.killAndCleanupLocked method · go · L460-L471 (12 LOC)
internal/skills/process/manager.go
func (b *ProcessBackend) killAndCleanupLocked() {
	if b.cmd != nil && b.cmd.Process != nil {
		b.cmd.Process.Kill() //nolint: errcheck
		b.cmd.Wait()         //nolint: errcheck
	}
	if b.stdin != nil {
		b.stdin.Close() //nolint: errcheck
	}
	b.cmd = nil
	b.stdin = nil
	b.readCh = nil
}
process.processTool.Execute method · go · L497-L518 (22 LOC)
internal/skills/process/manager.go
func (pt *processTool) Execute(ctx context.Context, input json.RawMessage) (tools.ToolResult, error) {
	resp, err := pt.backend.call(ctx, "tool/execute", map[string]any{
		"name":  pt.name,
		"input": input,
	})
	if err != nil {
		return tools.ToolResult{IsError: true, Content: err.Error()}, err
	}

	var toolResp struct {
		Content string `json:"content"`
		IsError bool   `json:"is_error"`
	}
	if err := json.Unmarshal(resp.Result, &toolResp); err != nil {
		return tools.ToolResult{IsError: true, Content: err.Error()}, fmt.Errorf("parse tool result: %w", err)
	}

	return tools.ToolResult{
		Content: toolResp.Content,
		IsError: toolResp.IsError,
	}, nil
}
process.parseHookPhase function · go · L524-L547 (24 LOC)
internal/skills/process/manager.go
func parseHookPhase(name string) skills.HookPhase {
	switch name {
	case "OnActivate":
		return skills.HookOnActivate
	case "OnDeactivate":
		return skills.HookOnDeactivate
	case "OnConversationStart":
		return skills.HookOnConversationStart
	case "OnBeforePromptBuild":
		return skills.HookOnBeforePromptBuild
	case "OnBeforeToolCall":
		return skills.HookOnBeforeToolCall
	case "OnAfterToolResult":
		return skills.HookOnAfterToolResult
	case "OnAfterResponse":
		return skills.HookOnAfterResponse
	case "OnBeforeWikiSection":
		return skills.HookOnBeforeWikiSection
	case "OnSecurityScanComplete":
		return skills.HookOnSecurityScanComplete
	default:
		return -1
	}
}
process.NewRequest function · go · L49-L65 (17 LOC)
internal/skills/process/protocol.go
func NewRequest(id int, method string, params any) (*JSONRPCRequest, error) {
	req := &JSONRPCRequest{
		JSONRPC: "2.0",
		ID:      id,
		Method:  method,
	}

	if params != nil {
		data, err := json.Marshal(params)
		if err != nil {
			return nil, fmt.Errorf("marshal params: %w", err)
		}
		req.Params = data
	}

	return req, nil
}
process.DecodeResponse function · go · L68-L74 (7 LOC)
internal/skills/process/protocol.go
func DecodeResponse(data []byte) (*JSONRPCResponse, error) {
	var resp JSONRPCResponse
	if err := json.Unmarshal(data, &resp); err != nil {
		return nil, fmt.Errorf("decode response: %w", err)
	}
	return &resp, nil
}
process.NewToolExecuteRequest function · go · L84-L90 (7 LOC)
internal/skills/process/protocol.go
func NewToolExecuteRequest(id int, name string, input json.RawMessage) (*JSONRPCRequest, error) {
	params := map[string]any{
		"name":  name,
		"input": input,
	}
	return NewRequest(id, "tool/execute", params)
}
process.NewHookHandleRequest function · go · L94-L100 (7 LOC)
internal/skills/process/protocol.go
func NewHookHandleRequest(id int, phase string, data map[string]any) (*JSONRPCRequest, error) {
	params := map[string]any{
		"phase": phase,
		"data":  data,
	}
	return NewRequest(id, "hook/handle", params)
}
main.main function · go · L42-L71 (30 LOC)
internal/skills/process/testdata/echo_skill.go
func main() {
	scanner := bufio.NewScanner(os.Stdin)
	// Increase buffer size for large messages.
	scanner.Buffer(make([]byte, 1024*1024), 1024*1024)

	for scanner.Scan() {
		line := scanner.Bytes()

		var req request
		if err := json.Unmarshal(line, &req); err != nil {
			writeError(0, -32700, fmt.Sprintf("parse error: %v", err))
			continue
		}

		switch req.Method {
		case "initialize":
			handleInitialize(req)
		case "tool/execute":
			handleToolExecute(req)
		case "hook/handle":
			handleHookHandle(req)
		case "shutdown":
			handleShutdown(req)
		case "slow/method":
			handleSlow(req)
		default:
			writeError(req.ID, -32601, fmt.Sprintf("method not found: %s", req.Method))
		}
	}
}
Repobility · code-quality intelligence · https://repobility.com
main.handleInitialize function · go · L73-L93 (21 LOC)
internal/skills/process/testdata/echo_skill.go
func handleInitialize(req request) {
	result := map[string]interface{}{
		"tools": []map[string]interface{}{
			{
				"name":        "echo",
				"description": "Echoes back the input",
				"input_schema": map[string]interface{}{
					"type": "object",
					"properties": map[string]interface{}{
						"message": map[string]interface{}{
							"type":        "string",
							"description": "The message to echo",
						},
					},
				},
			},
		},
		"hooks": []string{"OnBeforeToolCall"},
	}
	writeResult(req.ID, result)
}
main.handleToolExecute function · go · L95-L113 (19 LOC)
internal/skills/process/testdata/echo_skill.go
func handleToolExecute(req request) {
	var params map[string]json.RawMessage
	if err := json.Unmarshal(req.Params, &params); err != nil {
		writeError(req.ID, -32602, fmt.Sprintf("invalid params: %v", err))
		return
	}

	var name string
	if err := json.Unmarshal(params["name"], &name); err != nil {
		writeError(req.ID, -32602, fmt.Sprintf("invalid tool name: %v", err))
		return
	}

	result := map[string]interface{}{
		"content":  fmt.Sprintf("echo: tool=%s input=%s", name, string(params["input"])),
		"is_error": false,
	}
	writeResult(req.ID, result)
}
main.handleHookHandle function · go · L115-L121 (7 LOC)
internal/skills/process/testdata/echo_skill.go
func handleHookHandle(req request) {
	result := map[string]interface{}{
		"modified": map[string]interface{}{},
		"cancel":   false,
	}
	writeResult(req.ID, result)
}
‹ prevpage 6 / 11next ›