Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ repos:
hooks:
- id: go-fmt
name: go fmt
entry: bash -c 'gofmt -w -s . && git add -A'
entry: bash -c 'gofmt -w -s . && git add -u'
language: system
files: \.go$
pass_filenames: false
Expand Down
55 changes: 29 additions & 26 deletions cmd/pilotctl/appstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/TeoSlayer/pilotprotocol/pkg/telemetry"
"github.com/pilot-protocol/app-store/pkg/ipc"
"github.com/pilot-protocol/app-store/pkg/manifest"
"github.com/pilot-protocol/common/consent"
"github.com/pilot-protocol/common/crypto"
)

Expand Down Expand Up @@ -1212,33 +1213,35 @@ func cmdAppStoreInstall(args []string) {
Reason: reason,
})

// Emit a telemetry event for the successful install (consent-gated —
// no-op when PILOT_TELEMETRY_URL is empty or identity.json is absent).
// Best-effort: a send failure is logged but not fatal — the install
// itself already succeeded on disk.
// Emit a telemetry event for the successful install.
// Consent-gated (telemetry flag, default on). Best-effort: a send
// failure is logged but not fatal — the install already succeeded on disk.
{
url := os.Getenv("PILOT_TELEMETRY_URL")
if url == "" {
url = telemetry.DefaultEndpoint
}
sourceStr := "catalogue"
if source == installSourceLocal {
sourceStr = "local"
}
payload, _ := json.Marshal(map[string]string{
"app_id": m.ID,
"version": m.AppVersion,
"source": sourceStr,
})
identityPath := configDir() + "/identity.json"
client := telemetry.NewClientFromIdentity(url, identityPath, 0)
err := client.Send(telemetry.Event{
Kind: "app_installed",
TS: time.Now().UTC().Format(time.RFC3339),
Payload: payload,
})
if err != nil {
slog.Warn("telemetry send failed, install still successful", "app", m.ID, "err", err)
home, _ := os.UserHomeDir()
if consent.GetConsent(home, "telemetry") {
url := os.Getenv("PILOT_TELEMETRY_URL")
if url == "" {
url = telemetry.DefaultEndpoint
}
sourceStr := "catalogue"
if source == installSourceLocal {
sourceStr = "local"
}
payload, _ := json.Marshal(map[string]string{
"app_id": m.ID,
"version": m.AppVersion,
"source": sourceStr,
})
identityPath := configDir() + "/identity.json"
client := telemetry.NewClientFromIdentity(url, identityPath, 0)
err := client.Send(telemetry.Event{
Kind: "app_installed",
TS: time.Now().UTC().Format(time.RFC3339),
Payload: payload,
})
if err != nil {
slog.Warn("telemetry send failed, install still successful", "app", m.ID, "err", err)
}
}
}

Expand Down
11 changes: 6 additions & 5 deletions cmd/pilotctl/appstore_catalogue.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import (

"github.com/TeoSlayer/pilotprotocol/internal/catalogtrust"
"github.com/TeoSlayer/pilotprotocol/pkg/telemetry"
"github.com/pilot-protocol/common/consent"
)

// defaultCatalogueURL points at the canonical catalogue.json on main.
Expand Down Expand Up @@ -235,11 +236,11 @@ func cmdAppStoreSignCatalogue(args []string) {
}

func cmdAppStoreCatalogue(_ []string) {
// Emit a telemetry event for the catalogue page view (consent-gated —
// no-op when PILOT_TELEMETRY_URL is empty or identity.json is absent).
// Best-effort, non-blocking: a send failure is logged but doesn't
// prevent the catalogue from rendering.
{
// Emit a telemetry event for the catalogue page view.
// Consent-gated (telemetry flag, default on). Best-effort: a send
// failure is logged but doesn't prevent the catalogue from rendering.
home, _ := os.UserHomeDir()
if consent.GetConsent(home, "telemetry") {
url := os.Getenv("PILOT_TELEMETRY_URL")
if url == "" {
url = telemetry.DefaultEndpoint
Expand Down
43 changes: 23 additions & 20 deletions cmd/pilotctl/appstore_view.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/pilot-protocol/app-store/pkg/manifest"

"github.com/TeoSlayer/pilotprotocol/pkg/telemetry"
"github.com/pilot-protocol/common/consent"
)

// installedAppFacts is the verified, local-only band of `view` — derived
Expand Down Expand Up @@ -179,27 +180,29 @@ func cmdAppStoreView(args []string) {
"app %q not found in catalogue or install root", appID)
}

// Emit a telemetry event for the detail view (consent-gated —
// no-op when PILOT_TELEMETRY_URL is empty or identity.json is absent).
// Best-effort: a send failure is logged but not fatal — the view
// itself already resolved and rendered below.
// Emit a telemetry event for the detail view.
// Consent-gated (telemetry flag, default on). Best-effort: a send
// failure is logged but not fatal — the view already resolved and rendered below.
{
url := os.Getenv("PILOT_TELEMETRY_URL")
if url == "" {
url = telemetry.DefaultEndpoint
}
payload, _ := json.Marshal(map[string]string{
"app_id": appID,
})
identityPath := configDir() + "/identity.json"
client := telemetry.NewClientFromIdentity(url, identityPath, 0)
err := client.Send(telemetry.Event{
Kind: "appstore_view",
TS: time.Now().UTC().Format(time.RFC3339),
Payload: payload,
})
if err != nil {
slog.Warn("telemetry send failed, view still shown", "app", appID, "err", err)
home, _ := os.UserHomeDir()
if consent.GetConsent(home, "telemetry") {
url := os.Getenv("PILOT_TELEMETRY_URL")
if url == "" {
url = telemetry.DefaultEndpoint
}
payload, _ := json.Marshal(map[string]string{
"app_id": appID,
})
identityPath := configDir() + "/identity.json"
client := telemetry.NewClientFromIdentity(url, identityPath, 0)
err := client.Send(telemetry.Event{
Kind: "appstore_view",
TS: time.Now().UTC().Format(time.RFC3339),
Payload: payload,
})
if err != nil {
slog.Warn("telemetry send failed, view still shown", "app", appID, "err", err)
}
}
}

Expand Down
15 changes: 9 additions & 6 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -730,20 +730,23 @@ echo " reviews — occasional prompt to review installations"
echo " skillinject — auto-inject the Pilot Protocol skill into"
echo " agent toolchains"
echo ""
echo " Disable any feature by setting \"false\" in config.json:"
echo " Disable any feature by adding \"false\" entries under the \"consent\""
echo " key in config.json:"
echo " ${PILOT_DIR}/config.json"
echo ""
echo " \"telemetry\": false # suppress interest signals"
echo " \"broadcasts\": false # block agent-directed broadcasts"
echo " \"reviews\": false # suppress review prompts"
echo " {\"consent\": {"
echo " \"telemetry\": false, // suppress interest signals"
echo " \"broadcasts\": false, // block agent-directed broadcasts"
echo " \"reviews\": false // suppress review prompts"
echo " }}"
echo ""
echo " Skillinject has its own CLI commands:"
echo " pilotctl skills disable # remove injected skills, stop future ticks"
echo " pilotctl skills enable # re-install and re-enable"
echo ""
echo " Config changes take effect on daemon restart (or immediately for"
echo " skillinject). No data is sent to Pilot Protocol LLC or any third"
echo " party unless you explicitly enable it."
echo " skillinject). Telemetry features are ON by default (opt-out model)."
echo " Set the consent flags above to false to disable them."
echo ""
echo "============================================"
echo ""
Loading